发布 v2.3.2
This commit is contained in:
commit
83718c61cd
37
README.md
37
README.md
|
@ -18,6 +18,9 @@
|
||||||
* 文档框架 knife4j 美化接口文档
|
* 文档框架 knife4j 美化接口文档
|
||||||
* 代码生成器 一键生成前后端代码
|
* 代码生成器 一键生成前后端代码
|
||||||
|
|
||||||
|
## 参考文档
|
||||||
|
[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages)
|
||||||
|
|
||||||
## 修改RuoYi功能
|
## 修改RuoYi功能
|
||||||
|
|
||||||
### 依赖改动
|
### 依赖改动
|
||||||
|
@ -43,6 +46,8 @@
|
||||||
* 项目修改为 maven多环境配置
|
* 项目修改为 maven多环境配置
|
||||||
* 项目配置修改为 application.yml 统一管理
|
* 项目配置修改为 application.yml 统一管理
|
||||||
* 数据权限修改为 适配支持单表、多表
|
* 数据权限修改为 适配支持单表、多表
|
||||||
|
* 使用 redisson 实现 spring-cache 整合
|
||||||
|
* 增加 mybatis-plus 二级缓存 redis 存储
|
||||||
|
|
||||||
### 其他
|
### 其他
|
||||||
|
|
||||||
|
@ -59,38 +64,6 @@
|
||||||
<img src="https://images.gitee.com/uploads/images/2021/0525/101654_451e4523_1766278.jpeg" width="300px" height="450px" />
|
<img src="https://images.gitee.com/uploads/images/2021/0525/101654_451e4523_1766278.jpeg" width="300px" height="450px" />
|
||||||
<img src="https://images.gitee.com/uploads/images/2021/0525/101713_3d18b119_1766278.jpeg" width="300px" height="450px" />
|
<img src="https://images.gitee.com/uploads/images/2021/0525/101713_3d18b119_1766278.jpeg" width="300px" height="450px" />
|
||||||
|
|
||||||
## 重点注意事项
|
|
||||||
|
|
||||||
若依文档对事务注解的描述 [关于事务](https://doc.ruoyi.vip/ruoyi/document/htsc.html#%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86) 以下对多数据源事务做补充:
|
|
||||||
* 同一个事务下是无法切换数据源的
|
|
||||||
* 禁止 父方法使用 @Transactional 创建事务 子方法使用 @DataSource 切换数据源
|
|
||||||
* 正确用法: 子方法单独创建事务 或 父方法使用 @Transactional(propagation = Propagation.REQUIRES_NEW) 为所有子方法创建新事务
|
|
||||||
|
|
||||||
关于如何使用Tomcat
|
|
||||||
* 查看ruoyi-framework模块的pom.xml文件,根据注释更改依赖
|
|
||||||
* 查看ruoyi-admin模块中的application.yml文件,根据注释更改配置
|
|
||||||
|
|
||||||
关于如何创建新模块
|
|
||||||
* 参考ruoyi-demo模块
|
|
||||||
* 需要改动: 父pom 与 admin模块pom
|
|
||||||
|
|
||||||
关于树表生成
|
|
||||||
* 直接在mysql表中 添加 parentId orderNum 等字段(根据需要参考 TreeEntity类)
|
|
||||||
* 代码生成选择树表生成即可
|
|
||||||
|
|
||||||
关于数据权限
|
|
||||||
* 创建表 需预留 dept_id 字段 如需用户权限 还需预留 user_id 字段
|
|
||||||
* 支持 Mybatis-Plus 方式注入 参考 demo 模块用法(需导入 test.sql 文件)
|
|
||||||
* 支持 XML 方式注入 参考 system 模块用法
|
|
||||||
|
|
||||||
关于vue与boot整合部署
|
|
||||||
* [前端静态资源如何整合到后端访问](https://doc.ruoyi.vip/ruoyi-vue/other/faq.html#前端静态资源如何整合到后端访问)
|
|
||||||
|
|
||||||
关于修改包名
|
|
||||||
* 将文件夹全部修改为 com.xxx
|
|
||||||
* 使用IDEA全局替换 com.ruoyi 替换为 com.xxx
|
|
||||||
* 严禁手动修改
|
|
||||||
|
|
||||||
## 内置功能
|
## 内置功能
|
||||||
|
|
||||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||||
|
|
35
pom.xml
35
pom.xml
|
@ -13,7 +13,7 @@
|
||||||
<description>RuoYi-Vue-Plus后台管理系统</description>
|
<description>RuoYi-Vue-Plus后台管理系统</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<ruoyi-vue-plus.version>2.3.1</ruoyi-vue-plus.version>
|
<ruoyi-vue-plus.version>2.3.2</ruoyi-vue-plus.version>
|
||||||
<spring-boot.version>2.3.11.RELEASE</spring-boot.version>
|
<spring-boot.version>2.3.11.RELEASE</spring-boot.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
@ -21,7 +21,6 @@
|
||||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||||
<druid.version>1.2.6</druid.version>
|
<druid.version>1.2.6</druid.version>
|
||||||
<knife4j.version>3.0.2</knife4j.version>
|
<knife4j.version>3.0.2</knife4j.version>
|
||||||
<swagger-annotations.version>1.5.22</swagger-annotations.version>
|
|
||||||
<fastjson.version>1.2.76</fastjson.version>
|
<fastjson.version>1.2.76</fastjson.version>
|
||||||
<poi.version>4.1.2</poi.version>
|
<poi.version>4.1.2</poi.version>
|
||||||
<velocity.version>1.7</velocity.version>
|
<velocity.version>1.7</velocity.version>
|
||||||
|
@ -47,7 +46,7 @@
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--阿里数据库连接池 -->
|
<!-- 阿里数据库连接池 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
|
@ -58,18 +57,6 @@
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||||
<version>${knife4j.version}</version>
|
<version>${knife4j.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>swagger-annotations</artifactId>
|
|
||||||
<groupId>io.swagger</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.swagger</groupId>
|
|
||||||
<artifactId>swagger-annotations</artifactId>
|
|
||||||
<version>${swagger-annotations.version}</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- excel工具 -->
|
<!-- excel工具 -->
|
||||||
|
@ -79,7 +66,7 @@
|
||||||
<version>${poi.version}</version>
|
<version>${poi.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--velocity代码生成使用模板 -->
|
<!-- velocity代码生成使用模板 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.velocity</groupId>
|
<groupId>org.apache.velocity</groupId>
|
||||||
<artifactId>velocity</artifactId>
|
<artifactId>velocity</artifactId>
|
||||||
|
@ -93,7 +80,7 @@
|
||||||
<version>${fastjson.version}</version>
|
<version>${fastjson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--Token生成与解析-->
|
<!-- Token生成与解析-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt</artifactId>
|
<artifactId>jjwt</artifactId>
|
||||||
|
@ -139,6 +126,13 @@
|
||||||
<version>${spring-boot-admin.version}</version>
|
<version>${spring-boot-admin.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--redisson-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.redisson</groupId>
|
||||||
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
|
<version>${redisson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 定时任务-->
|
<!-- 定时任务-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
|
@ -181,13 +175,6 @@
|
||||||
<version>${ruoyi-vue-plus.version}</version>
|
<version>${ruoyi-vue-plus.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--redisson-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.redisson</groupId>
|
|
||||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
|
||||||
<version>${redisson.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|
|
@ -288,8 +288,6 @@ spring:
|
||||||
url: http://localhost:${server.port}${spring.boot.admin.context-path}
|
url: http://localhost:${server.port}${spring.boot.admin.context-path}
|
||||||
instance:
|
instance:
|
||||||
prefer-ip: true # 注册实例时,优先使用 IP
|
prefer-ip: true # 注册实例时,优先使用 IP
|
||||||
# username: ruoyi
|
|
||||||
# password: 123456
|
|
||||||
# Spring Boot Admin Server 服务端的相关配置
|
# Spring Boot Admin Server 服务端的相关配置
|
||||||
context-path: /admin # 配置 Spring
|
context-path: /admin # 配置 Spring
|
||||||
|
|
||||||
|
|
|
@ -136,11 +136,6 @@
|
||||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.swagger</groupId>
|
|
||||||
<artifactId>swagger-annotations</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
|
|
@ -17,7 +17,7 @@ import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色表 sys_role
|
* 角色表 sys_role
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ public class SysRole implements Serializable
|
||||||
@NotBlank(message = "显示顺序不能为空")
|
@NotBlank(message = "显示顺序不能为空")
|
||||||
private String roleSort;
|
private String roleSort;
|
||||||
|
|
||||||
/** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限) */
|
/** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
|
||||||
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限")
|
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
|
||||||
private String dataScope;
|
private String dataScope;
|
||||||
|
|
||||||
/** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
|
/** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
package com.ruoyi.common.core.mybatisplus;
|
||||||
|
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.ibatis.cache.Cache;
|
||||||
|
import org.springframework.data.redis.connection.RedisServerCommands;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mybatis-redis 二级缓存
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class MybatisPlusRedisCache implements Cache {
|
||||||
|
|
||||||
|
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
|
||||||
|
|
||||||
|
private RedisCache redisCache;
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
public MybatisPlusRedisCache(final String id) {
|
||||||
|
if (id == null) {
|
||||||
|
throw new IllegalArgumentException("Cache instances require an ID");
|
||||||
|
}
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putObject(Object key, Object value) {
|
||||||
|
if (redisCache == null) {
|
||||||
|
redisCache = SpringUtil.getBean(RedisCache.class);
|
||||||
|
}
|
||||||
|
if (value != null) {
|
||||||
|
redisCache.setCacheObject(key.toString(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject(Object key) {
|
||||||
|
if (redisCache == null) {
|
||||||
|
//由于启动期间注入失败,只能运行期间注入,这段代码可以删除
|
||||||
|
redisCache = SpringUtil.getBean(RedisCache.class);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (key != null) {
|
||||||
|
return redisCache.getCacheObject(key.toString());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("缓存出错");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object removeObject(Object key) {
|
||||||
|
if (redisCache == null) {
|
||||||
|
redisCache = SpringUtil.getBean(RedisCache.class);
|
||||||
|
}
|
||||||
|
if (key != null) {
|
||||||
|
redisCache.deleteObject(key.toString());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
log.debug("清空缓存");
|
||||||
|
if (redisCache == null) {
|
||||||
|
redisCache = SpringUtil.getBean(RedisCache.class);
|
||||||
|
}
|
||||||
|
Collection<String> keys = redisCache.keys("*:" + this.id + "*");
|
||||||
|
if (!CollectionUtils.isEmpty(keys)) {
|
||||||
|
redisCache.deleteObject(keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSize() {
|
||||||
|
RedisTemplate<String, Object> redisTemplate = SpringUtil.getBean("redisTemplate");
|
||||||
|
Long size = redisTemplate.execute(RedisServerCommands::dbSize);
|
||||||
|
return size.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReadWriteLock getReadWriteLock() {
|
||||||
|
return this.readWriteLock;
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,13 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页 Page 增强对象
|
||||||
|
*
|
||||||
|
* @param <T> 数据库实体
|
||||||
|
* @param <K> vo实体
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class PagePlus<T,K> implements IPage<T> {
|
public class PagePlus<T,K> implements IPage<T> {
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
package com.ruoyi.common.core.redis;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.lang.Validator;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import org.redisson.api.RCountDownLatch;
|
||||||
|
import org.redisson.api.RLock;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis 锁管理类
|
||||||
|
*
|
||||||
|
* @author shenxinquan
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RedisLockManager {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedissonClient redissonClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用锁
|
||||||
|
*/
|
||||||
|
private final static Integer BASE_LOCK = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公平锁
|
||||||
|
*/
|
||||||
|
private final static Integer FAIR_LOCK = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存放当前线程获取锁的类型
|
||||||
|
*/
|
||||||
|
private final ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取锁
|
||||||
|
*/
|
||||||
|
private RLock getLock(String key, Integer lockType) {
|
||||||
|
Assert.isTrue(StrUtil.isNotBlank(key), "key不能为空");
|
||||||
|
threadLocal.set(lockType);
|
||||||
|
RLock lock;
|
||||||
|
if (BASE_LOCK.equals(lockType)) {
|
||||||
|
lock = redissonClient.getLock(key);
|
||||||
|
} else if (FAIR_LOCK.equals(lockType)) {
|
||||||
|
lock = redissonClient.getFairLock(key);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("锁不存在!");
|
||||||
|
}
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取锁(不用设置超时时间,一直等待)
|
||||||
|
*/
|
||||||
|
public boolean getLock(String key) {
|
||||||
|
RLock lock = getLock(key, BASE_LOCK);
|
||||||
|
return lock.tryLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置过期时间
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param time 过期时间
|
||||||
|
* @param expireUnit 时间单位
|
||||||
|
*/
|
||||||
|
public boolean getLock(String key, long time, TimeUnit expireUnit) {
|
||||||
|
Assert.isTrue(time > 0, "过期时间必须大于0");
|
||||||
|
Assert.isTrue(Validator.isNotEmpty(expireUnit), "时间单位不能为空");
|
||||||
|
RLock lock = getLock(key, BASE_LOCK);
|
||||||
|
try {
|
||||||
|
return lock.tryLock(time, expireUnit);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置过期时间
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param waitTime 获取锁等待时间
|
||||||
|
* @param leaseTime 保留锁的时间
|
||||||
|
* @param expireUnit 时间单位
|
||||||
|
*/
|
||||||
|
public boolean getLock(String key, long waitTime, long leaseTime, TimeUnit expireUnit) {
|
||||||
|
Assert.isTrue(waitTime > 0, "获取锁等待时间必须大于0");
|
||||||
|
Assert.isTrue(leaseTime > 0, "保留锁的时间必须大于0");
|
||||||
|
Assert.isTrue(Validator.isNotEmpty(expireUnit), "时间单位不能为空");
|
||||||
|
RLock lock = getLock(key, BASE_LOCK);
|
||||||
|
try {
|
||||||
|
return lock.tryLock(waitTime, leaseTime, expireUnit);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取计数器锁
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param count countDownLatch 的数量
|
||||||
|
*/
|
||||||
|
public RCountDownLatch getCountDownLatch(String key, long count) {
|
||||||
|
Assert.isTrue(count >= 0, "count数量必须大于等于0");
|
||||||
|
RCountDownLatch rCountDownLatch = redissonClient.getCountDownLatch(key);
|
||||||
|
rCountDownLatch.trySetCount(count);
|
||||||
|
return rCountDownLatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取公平锁
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param waitTime 获取锁等待时间
|
||||||
|
* @param leaseTime 持有锁的时间
|
||||||
|
* @param expireUnit 时间单位
|
||||||
|
* @return
|
||||||
|
* @throws InterruptedException
|
||||||
|
*/
|
||||||
|
public boolean getFairLock(String key, long waitTime, long leaseTime, TimeUnit expireUnit) {
|
||||||
|
Assert.isTrue(waitTime > 0, "获取锁等待时间必须大于0");
|
||||||
|
Assert.isTrue(leaseTime > 0, "保留锁的时间必须大于0");
|
||||||
|
Assert.isTrue(Validator.isNotEmpty(expireUnit), "时间单位不能为空");
|
||||||
|
RLock lock = getLock(key, FAIR_LOCK);
|
||||||
|
try {
|
||||||
|
return lock.tryLock(waitTime, leaseTime, expireUnit);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取公平锁
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param leaseTime 持有锁的时间
|
||||||
|
* @param expireUnit 时间单位
|
||||||
|
*/
|
||||||
|
public boolean getFairLock(String key, long leaseTime, TimeUnit expireUnit) {
|
||||||
|
Assert.isTrue(leaseTime > 0, "保留锁的时间必须大于0");
|
||||||
|
Assert.isTrue(Validator.isNotEmpty(expireUnit), "时间单位不能为空");
|
||||||
|
RLock lock = getLock(key, FAIR_LOCK);
|
||||||
|
try {
|
||||||
|
return lock.tryLock(leaseTime, expireUnit);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放锁(统一释放)
|
||||||
|
*/
|
||||||
|
public void unLock(String key) {
|
||||||
|
Integer lockType = threadLocal.get();
|
||||||
|
RLock lock = getLock(key, lockType);
|
||||||
|
lock.unlock();
|
||||||
|
threadLocal.remove();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,26 +2,36 @@ package com.ruoyi.demo.controller;
|
||||||
|
|
||||||
import com.ruoyi.common.annotation.RedisLock;
|
import com.ruoyi.common.annotation.RedisLock;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.redis.RedisLockManager;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试分布式锁的样例
|
* 测试分布式锁的样例
|
||||||
*
|
*
|
||||||
* @author shenxinquan
|
* @author shenxinquan
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/demo/redisLock")
|
@RequestMapping("/demo/redisLock")
|
||||||
public class RedisLockController {
|
public class RedisLockController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisLockManager redisLockManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #p0 标识取第一个参数为redis锁的key
|
* #p0 标识取第一个参数为redis锁的key
|
||||||
*/
|
*/
|
||||||
@GetMapping("/getLock")
|
@GetMapping("/testLock1")
|
||||||
@RedisLock(expireTime = 10, key = "#p0")
|
@RedisLock(expireTime = 10, key = "#p0")
|
||||||
public AjaxResult<String> getLock(String key, String value) {
|
public AjaxResult<String> testLock1(String key, String value) {
|
||||||
try {
|
try {
|
||||||
// 同时请求排队
|
// 同时请求排队
|
||||||
// Thread.sleep(5000);
|
// Thread.sleep(5000);
|
||||||
|
@ -32,4 +42,34 @@ public class RedisLockController {
|
||||||
}
|
}
|
||||||
return AjaxResult.success("操作成功",value);
|
return AjaxResult.success("操作成功",value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试锁工具类
|
||||||
|
*/
|
||||||
|
@GetMapping("/testLock2")
|
||||||
|
public AjaxResult<Void> testLock(String key, Long time) {
|
||||||
|
try {
|
||||||
|
boolean flag = redisLockManager.getLock(key, time, TimeUnit.SECONDS);
|
||||||
|
if (flag) {
|
||||||
|
log.info("获取锁成功: " + key);
|
||||||
|
Thread.sleep(3000);
|
||||||
|
redisLockManager.unLock(key);
|
||||||
|
log.info("释放锁成功: " + key);
|
||||||
|
} else {
|
||||||
|
log.error("获取锁失败: " + key);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试spring-cache注解
|
||||||
|
*/
|
||||||
|
@Cacheable(value = "test", key = "#key")
|
||||||
|
@GetMapping("/testCache")
|
||||||
|
public AjaxResult<String> testCache(String key) {
|
||||||
|
return AjaxResult.success("操作成功", key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.ruoyi.demo.mapper;
|
package com.ruoyi.demo.mapper;
|
||||||
|
|
||||||
import com.ruoyi.demo.domain.TestDemo;
|
import com.ruoyi.common.core.mybatisplus.MybatisPlusRedisCache;
|
||||||
import com.ruoyi.common.core.page.BaseMapperPlus;
|
import com.ruoyi.common.core.page.BaseMapperPlus;
|
||||||
|
import com.ruoyi.demo.domain.TestDemo;
|
||||||
|
import org.apache.ibatis.annotations.CacheNamespace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试单表Mapper接口
|
* 测试单表Mapper接口
|
||||||
|
@ -9,6 +11,7 @@ import com.ruoyi.common.core.page.BaseMapperPlus;
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
* @date 2021-05-30
|
* @date 2021-05-30
|
||||||
*/
|
*/
|
||||||
|
@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
|
||||||
public interface TestDemoMapper extends BaseMapperPlus<TestDemo> {
|
public interface TestDemoMapper extends BaseMapperPlus<TestDemo> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.ruoyi.demo.mapper;
|
package com.ruoyi.demo.mapper;
|
||||||
|
|
||||||
import com.ruoyi.demo.domain.TestTree;
|
import com.ruoyi.common.core.mybatisplus.MybatisPlusRedisCache;
|
||||||
import com.ruoyi.common.core.page.BaseMapperPlus;
|
import com.ruoyi.common.core.page.BaseMapperPlus;
|
||||||
|
import com.ruoyi.demo.domain.TestTree;
|
||||||
|
import org.apache.ibatis.annotations.CacheNamespace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试树表Mapper接口
|
* 测试树表Mapper接口
|
||||||
|
@ -9,6 +11,7 @@ import com.ruoyi.common.core.page.BaseMapperPlus;
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
* @date 2021-05-30
|
* @date 2021-05-30
|
||||||
*/
|
*/
|
||||||
|
@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
|
||||||
public interface TestTreeMapper extends BaseMapperPlus<TestTree> {
|
public interface TestTreeMapper extends BaseMapperPlus<TestTree> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.ruoyi.framework.aspectj;
|
||||||
|
|
||||||
import com.ruoyi.common.annotation.RedisLock;
|
import com.ruoyi.common.annotation.RedisLock;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.core.redis.RedisLockManager;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
@ -33,7 +34,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
public class RedisLockAspect {
|
public class RedisLockAspect {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedissonClient redissonClient;
|
private RedisLockManager redisLockManager;
|
||||||
|
|
||||||
@Pointcut("@annotation(com.ruoyi.common.annotation.RedisLock)")
|
@Pointcut("@annotation(com.ruoyi.common.annotation.RedisLock)")
|
||||||
public void annotationPointcut() {
|
public void annotationPointcut() {
|
||||||
|
@ -70,14 +71,16 @@ public class RedisLockAspect {
|
||||||
key = Constants.REDIS_LOCK_KEY + key;
|
key = Constants.REDIS_LOCK_KEY + key;
|
||||||
Object res;
|
Object res;
|
||||||
try {
|
try {
|
||||||
if (acquire(key, expireTime, TimeUnit.SECONDS)) {
|
if (redisLockManager.getLock(key, expireTime, TimeUnit.SECONDS)) {
|
||||||
|
log.info("lock => key : " + key + " , ThreadName : " + Thread.currentThread().getName());
|
||||||
try {
|
try {
|
||||||
res = joinPoint.proceed();
|
res = joinPoint.proceed();
|
||||||
return res;
|
return res;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} finally {
|
} finally {
|
||||||
release(key);
|
redisLockManager.unLock(key);
|
||||||
|
log.info("unlock => key : " + key + " , ThreadName : " + Thread.currentThread().getName());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("redis分布式锁注解参数异常");
|
throw new RuntimeException("redis分布式锁注解参数异常");
|
||||||
|
@ -133,32 +136,4 @@ public class RedisLockAspect {
|
||||||
return listPar;
|
return listPar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 加锁(RLock)带超时时间的
|
|
||||||
*/
|
|
||||||
private boolean acquire(String key, long expire, TimeUnit expireUnit) {
|
|
||||||
try {
|
|
||||||
//获取锁对象
|
|
||||||
RLock mylock = redissonClient.getLock(key);
|
|
||||||
//加锁,并且设置锁过期时间,防止死锁的产生
|
|
||||||
mylock.tryLock(expire, expire, expireUnit);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
log.info("lock => key : " + key + " , ThreadName : " + Thread.currentThread().getName());
|
|
||||||
//加锁成功
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 锁的释放
|
|
||||||
*/
|
|
||||||
private void release(String lockName) {
|
|
||||||
//获取所对象
|
|
||||||
RLock mylock = redissonClient.getLock(lockName);
|
|
||||||
//释放锁(解锁)
|
|
||||||
mylock.unlock();
|
|
||||||
log.info("unlock => key : " + lockName + " , ThreadName : " + Thread.currentThread().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,11 @@ import java.util.Arrays;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步配置
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
@Configuration
|
@Configuration
|
||||||
public class AsyncConfig extends AsyncConfigurerSupport {
|
public class AsyncConfig extends AsyncConfigurerSupport {
|
||||||
|
|
|
@ -6,15 +6,20 @@ import org.redisson.Redisson;
|
||||||
import org.redisson.api.RedissonClient;
|
import org.redisson.api.RedissonClient;
|
||||||
import org.redisson.codec.JsonJacksonCodec;
|
import org.redisson.codec.JsonJacksonCodec;
|
||||||
import org.redisson.config.Config;
|
import org.redisson.config.Config;
|
||||||
|
import org.redisson.spring.cache.CacheConfig;
|
||||||
|
import org.redisson.spring.cache.RedissonSpringCacheManager;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||||
import org.springframework.cache.annotation.EnableCaching;
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* redis配置
|
* redis配置
|
||||||
|
@ -67,4 +72,15 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||||
.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
|
.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
|
||||||
return Redisson.create(config);
|
return Redisson.create(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 整合spring-cache
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public CacheManager cacheManager(RedissonClient redissonClient) {
|
||||||
|
Map<String, CacheConfig> config = new HashMap<>();
|
||||||
|
config.put("redissonCacheMap", new CacheConfig(30*60*1000, 10*60*1000));
|
||||||
|
return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用配置
|
* 通用配置
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -31,8 +31,7 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||||
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
|
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
|
||||||
|
|
||||||
/** swagger配置 */
|
/** swagger配置 */
|
||||||
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
|
registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
|
||||||
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,4 +62,4 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||||
source.registerCorsConfiguration("/**", config);
|
source.registerCorsConfiguration("/**", config);
|
||||||
return new CorsFilter(source);
|
return new CorsFilter(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.ruoyi.framework.config;
|
||||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||||
import com.ruoyi.framework.config.properties.SwaggerProperties;
|
import com.ruoyi.framework.config.properties.SwaggerProperties;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import io.swagger.models.auth.In;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
@ -13,18 +14,16 @@ import springfox.documentation.service.*;
|
||||||
import springfox.documentation.spi.DocumentationType;
|
import springfox.documentation.spi.DocumentationType;
|
||||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swagger2的接口配置
|
* Swagger 文档配置
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableSwagger2
|
|
||||||
@EnableKnife4j
|
@EnableKnife4j
|
||||||
public class SwaggerConfig {
|
public class SwaggerConfig {
|
||||||
|
|
||||||
|
@ -36,7 +35,7 @@ public class SwaggerConfig {
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public Docket createRestApi() {
|
public Docket createRestApi() {
|
||||||
return new Docket(DocumentationType.SWAGGER_2)
|
return new Docket(DocumentationType.OAS_30)
|
||||||
.enable(swaggerProperties.getEnabled())
|
.enable(swaggerProperties.getEnabled())
|
||||||
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||||
.apiInfo(apiInfo())
|
.apiInfo(apiInfo())
|
||||||
|
@ -60,7 +59,7 @@ public class SwaggerConfig {
|
||||||
*/
|
*/
|
||||||
private List<SecurityScheme> securitySchemes() {
|
private List<SecurityScheme> securitySchemes() {
|
||||||
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
|
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
|
||||||
apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
|
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
|
||||||
return apiKeyList;
|
return apiKeyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +71,7 @@ public class SwaggerConfig {
|
||||||
securityContexts.add(
|
securityContexts.add(
|
||||||
SecurityContext.builder()
|
SecurityContext.builder()
|
||||||
.securityReferences(defaultAuth())
|
.securityReferences(defaultAuth())
|
||||||
.forPaths(PathSelectors.regex("^(?!auth).*$"))
|
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
|
||||||
.build());
|
.build());
|
||||||
return securityContexts;
|
return securityContexts;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证码 配置属性
|
* swagger 配置属性
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证码 配置属性
|
* 线程池 配置属性
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,6 +4,11 @@ import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token 配置属性
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties(prefix = "token")
|
@ConfigurationProperties(prefix = "token")
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证码 配置属性
|
* xss过滤 配置属性
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
@ -28,7 +29,7 @@ import io.swagger.annotations.ApiOperation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ${functionName}Controller
|
* ${functionName}Controller
|
||||||
*
|
*
|
||||||
* @author ${author}
|
* @author ${author}
|
||||||
* @date ${datetime}
|
* @date ${datetime}
|
||||||
*/
|
*/
|
||||||
|
@ -87,6 +88,7 @@ public class ${ClassName}Controller extends BaseController {
|
||||||
@ApiOperation("新增${functionName}")
|
@ApiOperation("新增${functionName}")
|
||||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
|
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
|
||||||
@Log(title = "${functionName}", businessType = BusinessType.INSERT)
|
@Log(title = "${functionName}", businessType = BusinessType.INSERT)
|
||||||
|
@RepeatSubmit
|
||||||
@PostMapping()
|
@PostMapping()
|
||||||
public AjaxResult<Void> add(@Validated @RequestBody ${ClassName}AddBo bo) {
|
public AjaxResult<Void> add(@Validated @RequestBody ${ClassName}AddBo bo) {
|
||||||
return toAjax(i${ClassName}Service.insertByAddBo(bo) ? 1 : 0);
|
return toAjax(i${ClassName}Service.insertByAddBo(bo) ? 1 : 0);
|
||||||
|
@ -98,6 +100,7 @@ public class ${ClassName}Controller extends BaseController {
|
||||||
@ApiOperation("修改${functionName}")
|
@ApiOperation("修改${functionName}")
|
||||||
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
|
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
|
||||||
@Log(title = "${functionName}", businessType = BusinessType.UPDATE)
|
@Log(title = "${functionName}", businessType = BusinessType.UPDATE)
|
||||||
|
@RepeatSubmit
|
||||||
@PutMapping()
|
@PutMapping()
|
||||||
public AjaxResult<Void> edit(@Validated @RequestBody ${ClassName}EditBo bo) {
|
public AjaxResult<Void> edit(@Validated @RequestBody ${ClassName}EditBo bo) {
|
||||||
return toAjax(i${ClassName}Service.updateByEditBo(bo) ? 1 : 0);
|
return toAjax(i${ClassName}Service.updateByEditBo(bo) ? 1 : 0);
|
||||||
|
|
|
@ -2,6 +2,8 @@ package ${packageName}.mapper;
|
||||||
|
|
||||||
import ${packageName}.domain.${ClassName};
|
import ${packageName}.domain.${ClassName};
|
||||||
import com.ruoyi.common.core.page.BaseMapperPlus;
|
import com.ruoyi.common.core.page.BaseMapperPlus;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.MybatisPlusRedisCache;
|
||||||
|
import org.apache.ibatis.annotations.CacheNamespace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ${functionName}Mapper接口
|
* ${functionName}Mapper接口
|
||||||
|
@ -9,6 +11,7 @@ import com.ruoyi.common.core.page.BaseMapperPlus;
|
||||||
* @author ${author}
|
* @author ${author}
|
||||||
* @date ${datetime}
|
* @date ${datetime}
|
||||||
*/
|
*/
|
||||||
|
@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
|
||||||
public interface ${ClassName}Mapper extends BaseMapperPlus<${ClassName}> {
|
public interface ${ClassName}Mapper extends BaseMapperPlus<${ClassName}> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -541,7 +541,7 @@ export default {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -599,7 +599,7 @@ export default {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
/** ${subTable.functionName}序号 */
|
/** ${subTable.functionName}序号 */
|
||||||
|
@ -648,7 +648,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "ruoyi-vue-plus",
|
"name": "ruoyi-vue-plus",
|
||||||
"version": "2.3.1",
|
"version": "2.3.2",
|
||||||
"description": "RuoYi-Vue-Plus后台管理系统",
|
"description": "RuoYi-Vue-Plus后台管理系统",
|
||||||
"author": "LionLi",
|
"author": "LionLi",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
@ -75,7 +75,7 @@ export default {
|
||||||
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
||||||
[{ align: [] }], // 对齐方式
|
[{ align: [] }], // 对齐方式
|
||||||
["clean"], // 清除文本格式
|
["clean"], // 清除文本格式
|
||||||
["link", "image"] // 链接、图片
|
["link", "image", "video"] // 链接、图片、视频
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
placeholder: "请输入内容",
|
placeholder: "请输入内容",
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<div class="right-menu">
|
<div class="right-menu">
|
||||||
<template v-if="device!=='mobile'">
|
<template v-if="device!=='mobile'">
|
||||||
<search id="header-search" class="right-menu-item" />
|
<search id="header-search" class="right-menu-item" />
|
||||||
|
|
||||||
<el-tooltip content="源码地址" effect="dark" placement="bottom">
|
<el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||||
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
@ -104,7 +104,7 @@ export default {
|
||||||
this.$store.dispatch('LogOut').then(() => {
|
this.$store.dispatch('LogOut').then(() => {
|
||||||
location.href = '/index';
|
location.href = '/index';
|
||||||
})
|
})
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ service.interceptors.response.use(res => {
|
||||||
store.dispatch('LogOut').then(() => {
|
store.dispatch('LogOut').then(() => {
|
||||||
location.href = '/index';
|
location.href = '/index';
|
||||||
})
|
})
|
||||||
})
|
}).catch(() => {});
|
||||||
} else if (code === 500) {
|
} else if (code === 500) {
|
||||||
Message({
|
Message({
|
||||||
message: msg,
|
message: msg,
|
||||||
|
|
|
@ -80,6 +80,17 @@
|
||||||
<span>更新日志</span>
|
<span>更新日志</span>
|
||||||
</div>
|
</div>
|
||||||
<el-collapse accordion>
|
<el-collapse accordion>
|
||||||
|
<el-collapse-item title="v2.3.2 - 2021-6-11">
|
||||||
|
<ol>
|
||||||
|
<li>add redis锁工具类编写</li>
|
||||||
|
<li>update spring-cache 整合 redisson</li>
|
||||||
|
<li>update MybatisPlus整合Redis二级缓存</li>
|
||||||
|
<li>update swagger 升级为 3.0.0 使用 OAS_30 协议</li>
|
||||||
|
<li>update 优化 代码生成器 增加表单防重注解</li>
|
||||||
|
<li>update 优化 锁切面代码 key到常量类</li>
|
||||||
|
<li>fix 修复相对路径上传异常问题</li>
|
||||||
|
</ol>
|
||||||
|
</el-collapse-item>
|
||||||
<el-collapse-item title="v2.3.1 - 2021-6-4">
|
<el-collapse-item title="v2.3.1 - 2021-6-4">
|
||||||
<ol>
|
<ol>
|
||||||
<li>add 增加 redisson 分布式锁 注解与demo案例</li>
|
<li>add 增加 redisson 分布式锁 注解与demo案例</li>
|
||||||
|
|
|
@ -410,7 +410,7 @@ export default {
|
||||||
return runJob(row.jobId, row.jobGroup);
|
return runJob(row.jobId, row.jobGroup);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.msgSuccess("执行成功");
|
this.msgSuccess("执行成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 任务详细信息 */
|
/** 任务详细信息 */
|
||||||
handleView(row) {
|
handleView(row) {
|
||||||
|
@ -471,7 +471,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -486,7 +486,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -269,7 +269,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 清空按钮操作 */
|
/** 清空按钮操作 */
|
||||||
handleClean() {
|
handleClean() {
|
||||||
|
@ -282,7 +282,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("清空成功");
|
this.msgSuccess("清空成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -297,7 +297,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -202,7 +202,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 清空按钮操作 */
|
/** 清空按钮操作 */
|
||||||
handleClean() {
|
handleClean() {
|
||||||
|
@ -215,7 +215,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("清空成功");
|
this.msgSuccess("清空成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -230,7 +230,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -120,7 +120,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("强退成功");
|
this.msgSuccess("强退成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -290,7 +290,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 清空按钮操作 */
|
/** 清空按钮操作 */
|
||||||
handleClean() {
|
handleClean() {
|
||||||
|
@ -303,7 +303,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("清空成功");
|
this.msgSuccess("清空成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -318,7 +318,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -338,7 +338,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -353,7 +353,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 刷新缓存按钮操作 */
|
/** 刷新缓存按钮操作 */
|
||||||
handleRefreshCache() {
|
handleRefreshCache() {
|
||||||
|
|
|
@ -57,17 +57,17 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-edit"
|
icon="el-icon-edit"
|
||||||
@click="handleUpdate(scope.row)"
|
@click="handleUpdate(scope.row)"
|
||||||
v-hasPermi="['system:dept:edit']"
|
v-hasPermi="['system:dept:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
@click="handleAdd(scope.row)"
|
@click="handleAdd(scope.row)"
|
||||||
v-hasPermi="['system:dept:add']"
|
v-hasPermi="['system:dept:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
|
@ -310,8 +310,8 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -337,7 +337,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -352,7 +352,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -342,7 +342,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -357,7 +357,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 刷新缓存按钮操作 */
|
/** 刷新缓存按钮操作 */
|
||||||
handleRefreshCache() {
|
handleRefreshCache() {
|
||||||
|
|
|
@ -163,7 +163,7 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item v-if="form.menuType != 'M'" label="权限标识">
|
<el-form-item v-if="form.menuType != 'M'" label="权限标识">
|
||||||
<el-input v-model="form.perms" placeholder="请权限标识" maxlength="100" />
|
<el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
|
@ -393,7 +393,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -336,7 +336,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -309,7 +309,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -324,7 +324,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -593,7 +593,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -608,7 +608,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -631,7 +631,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
|
@ -646,7 +646,7 @@ export default {
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
this.download(response.msg);
|
this.download(response.msg);
|
||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 导入按钮操作 */
|
/** 导入按钮操作 */
|
||||||
handleImport() {
|
handleImport() {
|
||||||
|
|
|
@ -283,7 +283,7 @@ export default {
|
||||||
return synchDb(tableName);
|
return synchDb(tableName);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.msgSuccess("同步成功");
|
this.msgSuccess("同步成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 打开导入表弹窗 */
|
/** 打开导入表弹窗 */
|
||||||
openImportTable() {
|
openImportTable() {
|
||||||
|
@ -333,7 +333,7 @@ export default {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.msgSuccess("删除成功");
|
this.msgSuccess("删除成功");
|
||||||
})
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue