疯狂的狮子li
2021-06-01 c90ca8c2a63edcacab53a5f3156a561c01439936
发布 v2.3.0
已修改34个文件
已添加40个文件
3794 ■■■■■ 文件已修改
README.md 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-dev.yml 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-prod.yml 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/ChkjTestAddBo.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/ChkjTestEditBo.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/ChkjTestQueryBo.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestDemoAddBo.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestDemoEditBo.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestDemoQueryBo.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestTreeAddBo.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestTreeEditBo.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestTreeQueryBo.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/ChkjTestController.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/domain/ChkjTest.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/ChkjTestMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/service/IChkjTestService.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestTreeService.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/ChkjTestServiceImpl.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/vo/ChkjTestVo.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/vo/TestDemoVo.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/java/com/ruoyi/demo/vo/TestTreeVo.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/resources/mapper/demo/ChkjTestMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/resources/mapper/demo/TestDemoMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-demo/src/main/resources/mapper/demo/TestTreeMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/addBo.java.vm 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/domain.java.vm 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/service.java.vm 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/vo.java.vm 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/demo/demo.js 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/demo/test.js 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/demo/tree.js 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/demo/demo/index.vue 339 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/demo/test/index.vue 361 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/demo/tree/index.vue 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ry.bat 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ry.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/test.sql 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -28,6 +28,7 @@
* é›†æˆ Feign æŽ¥å£åŒ–管理 Http è¯·æ±‚(如三方请求 æ”¯ä»˜,短信,推送等)
* ç§»é™¤ è‡ªå¸¦æœåŠ¡ç›‘æŽ§ æ”¹ä¸º spring-boot-admin å…¨æ–¹ä½ç›‘控
* å¢žåŠ  demo æ¨¡å—示例(给不会增加模块的小伙伴做参考)
* å¢žåŠ  redisson æ”¯æŒåˆ†å¸ƒå¼é” åŠŸèƒ½æ›´å¼ºå¤§
### ä»£ç æ”¹åЍ
@@ -38,6 +39,7 @@
* ä»£ç ç”Ÿæˆæ¨¡æ¿ å¢žåŠ  æ–‡æ¡£æ³¨è§£ ä¸Ž æ ¡éªŒæ³¨è§£ ç®€åŒ–通用操作
* é¡¹ç›®ä¿®æ”¹ä¸º maven多环境配置
* é¡¹ç›®é…ç½®ä¿®æ”¹ä¸º application.yml ç»Ÿä¸€ç®¡ç†
* æ•°æ®æƒé™ä¿®æ”¹ä¸º é€‚配支持单表、多表
### å…¶ä»–
@@ -73,8 +75,9 @@
* ä»£ç ç”Ÿæˆé€‰æ‹©æ ‘表生成即可
关于数据权限
* å‚考(用户,角色,部门)列表接口用法
* ç›®å‰ä»…支持 XML æ–¹å¼ä½¿ç”¨(后续修改为支持MP)
* åˆ›å»ºè¡¨ éœ€é¢„ç•™ dept_id å­—段 å¦‚需用户权限 è¿˜éœ€é¢„ç•™ user_id å­—段
* æ”¯æŒ Mybatis-Plus æ–¹å¼æ³¨å…¥ å‚考 demo æ¨¡å—用法(需导入 test.sql æ–‡ä»¶)
* æ”¯æŒ XML æ–¹å¼æ³¨å…¥ å‚考 system æ¨¡å—用法
关于vue与boot整合部署  
* [前端静态资源如何整合到后端访问](https://doc.ruoyi.vip/ruoyi-vue/other/faq.html#前端静态资源如何整合到后端访问)
pom.xml
@@ -13,7 +13,7 @@
    <description>RuoYi-Vue-Plus后台管理系统</description>
    <properties>
        <ruoyi-vue-plus.version>2.2.1</ruoyi-vue-plus.version>
        <ruoyi-vue-plus.version>2.3.0</ruoyi-vue-plus.version>
        <spring-boot.version>2.3.11.RELEASE</spring-boot.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
@@ -31,6 +31,7 @@
        <feign.version>2.2.6.RELEASE</feign.version>
        <feign-okhttp.version>11.0</feign-okhttp.version>
        <spring-boot-admin.version>2.3.1</spring-boot-admin.version>
        <redisson.version>3.15.2</redisson.version>
    </properties>
    <!-- ä¾èµ–声明 -->
@@ -180,6 +181,13 @@
                <version>${ruoyi-vue-plus.version}</version>
            </dependency>
            <!--redisson-->
            <dependency>
                <groupId>org.redisson</groupId>
                <artifactId>redisson-spring-boot-starter</artifactId>
                <version>${redisson.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
ruoyi-admin/src/main/resources/application-dev.yml
@@ -67,13 +67,38 @@
    password:
    # è¿žæŽ¥è¶…æ—¶æ—¶é—´
    timeout: 10s
    lettuce:
      pool:
        # è¿žæŽ¥æ± ä¸­çš„æœ€å°ç©ºé—²è¿žæŽ¥
        min-idle: 0
        # è¿žæŽ¥æ± ä¸­çš„æœ€å¤§ç©ºé—²è¿žæŽ¥
        max-idle: 8
        # è¿žæŽ¥æ± çš„æœ€å¤§æ•°æ®åº“连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
    # æ˜¯å¦å¼€å¯ssl
    ssl: false
--- # redisson å®¢æˆ·ç«¯é…ç½®
redisson:
  # çº¿ç¨‹æ± æ•°é‡
  threads: 16
  # Netty线程池数量
  nettyThreads: 32
  # ä¼ è¾“模式
  transportMode: "NIO"
  # å•节点配置
  singleServerConfig:
    # å®¢æˆ·ç«¯åç§°
    clientName: ${ruoyi-vue-plus.name}
    # æœ€å°ç©ºé—²è¿žæŽ¥æ•°
    connectionMinimumIdleSize: 32
    # è¿žæŽ¥æ± å¤§å°
    connectionPoolSize: 64
    # è¿žæŽ¥ç©ºé—²è¶…时,单位:毫秒
    idleConnectionTimeout: 10000
    # å‘½ä»¤ç­‰å¾…超时,单位:毫秒
    timeout: 3000
    # å¦‚果尝试在此限制之内发送成功,则开始启用 timeout è®¡æ—¶ã€‚
    retryAttempts: 3
    # å‘½ä»¤é‡è¯•发送时间间隔,单位:毫秒
    retryInterval: 1500
    # å‘布和订阅连接的最小空闲连接数
    subscriptionConnectionMinimumIdleSize: 1
    # å‘布和订阅连接池大小
    subscriptionConnectionPoolSize: 50
    # å•个连接最大订阅数量
    subscriptionsPerConnection: 5
    # DNS监测时间间隔,单位:毫秒
    dnsMonitoringInterval: 5000
ruoyi-admin/src/main/resources/application-prod.yml
@@ -67,13 +67,38 @@
    password:
    # è¿žæŽ¥è¶…æ—¶æ—¶é—´
    timeout: 10s
    lettuce:
      pool:
        # è¿žæŽ¥æ± ä¸­çš„æœ€å°ç©ºé—²è¿žæŽ¥
        min-idle: 0
        # è¿žæŽ¥æ± ä¸­çš„æœ€å¤§ç©ºé—²è¿žæŽ¥
        max-idle: 8
        # è¿žæŽ¥æ± çš„æœ€å¤§æ•°æ®åº“连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
    # æ˜¯å¦å¼€å¯ssl
    ssl: false
--- # redisson å®¢æˆ·ç«¯é…ç½®
redisson:
  # çº¿ç¨‹æ± æ•°é‡
  threads: 16
  # Netty线程池数量
  nettyThreads: 32
  # ä¼ è¾“模式
  transportMode: "NIO"
  # å•节点配置
  singleServerConfig:
    # å®¢æˆ·ç«¯åç§°
    clientName: ${ruoyi-vue-plus.name}
    # æœ€å°ç©ºé—²è¿žæŽ¥æ•°
    connectionMinimumIdleSize: 32
    # è¿žæŽ¥æ± å¤§å°
    connectionPoolSize: 64
    # è¿žæŽ¥ç©ºé—²è¶…时,单位:毫秒
    idleConnectionTimeout: 10000
    # å‘½ä»¤ç­‰å¾…超时,单位:毫秒
    timeout: 3000
    # å¦‚果尝试在此限制之内发送成功,则开始启用 timeout è®¡æ—¶ã€‚
    retryAttempts: 3
    # å‘½ä»¤é‡è¯•发送时间间隔,单位:毫秒
    retryInterval: 1500
    # å‘布和订阅连接的最小空闲连接数
    subscriptionConnectionMinimumIdleSize: 1
    # å‘布和订阅连接池大小
    subscriptionConnectionPoolSize: 50
    # å•个连接最大订阅数量
    subscriptionsPerConnection: 5
    # DNS监测时间间隔,单位:毫秒
    dnsMonitoringInterval: 5000
ruoyi-common/pom.xml
@@ -151,6 +151,12 @@
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
        <!--redisson-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
</project>
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
@@ -25,4 +25,9 @@
     * ç”¨æˆ·è¡¨çš„别名
     */
    public String userAlias() default "";
    /**
     * æ˜¯å¦è¿‡æ»¤ç”¨æˆ·æƒé™
     */
    public boolean isUser() default false;
}
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
@@ -1,29 +1,24 @@
package com.ruoyi.common.core.redis;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Lists;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * spring redis å·¥å…·ç±»
 *
 * @author ruoyi
 * @author shenxinquan
 **/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{
public class RedisCache {
    @Autowired
    public RedisTemplate redisTemplate;
    private RedissonClient redissonClient;
    /**
     * ç¼“存基本的对象,Integer、String、实体类等
@@ -31,9 +26,8 @@
     * @param key ç¼“存的键值
     * @param value ç¼“存的值
     */
    public <T> void setCacheObject(final String key, final T value)
    {
        redisTemplate.opsForValue().set(key, value);
    public <T> void setCacheObject(final String key, final T value) {
        redissonClient.getBucket(key).set(value);
    }
    /**
@@ -44,9 +38,10 @@
     * @param timeout æ—¶é—´
     * @param timeUnit æ—¶é—´é¢—粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
    {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
        RBucket<T> result = redissonClient.getBucket(key);
        result.set(value);
        result.expire(timeout, timeUnit);
    }
    /**
@@ -56,8 +51,7 @@
     * @param timeout è¶…æ—¶æ—¶é—´
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout)
    {
    public boolean expire(final String key, final long timeout) {
        return expire(key, timeout, TimeUnit.SECONDS);
    }
@@ -69,9 +63,9 @@
     * @param unit æ—¶é—´å•位
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit)
    {
        return redisTemplate.expire(key, timeout, unit);
    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
        RBucket rBucket = redissonClient.getBucket(key);
        return rBucket.expire(timeout, unit);
    }
    /**
@@ -80,10 +74,9 @@
     * @param key ç¼“存键值
     * @return ç¼“存键值对应的数据
     */
    public <T> T getCacheObject(final String key)
    {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    public <T> T getCacheObject(final String key) {
        RBucket<T> rBucket = redissonClient.getBucket(key);
        return rBucket.get();
    }
    /**
@@ -91,10 +84,11 @@
     *
     * @param key
     */
    public boolean deleteObject(final String key)
    {
        return redisTemplate.delete(key);
    public boolean deleteObject(final String key) {
        return redissonClient.getBucket(key).delete();
    }
    /* */
    /**
     * åˆ é™¤é›†åˆå¯¹è±¡
@@ -102,9 +96,8 @@
     * @param collection å¤šä¸ªå¯¹è±¡
     * @return
     */
    public long deleteObject(final Collection collection)
    {
        return redisTemplate.delete(collection);
    public long deleteObject(final Collection collection) {
        return redissonClient.getKeys().delete(Arrays.toString(collection.toArray()));
    }
    /**
@@ -114,10 +107,9 @@
     * @param dataList å¾…缓存的List数据
     * @return ç¼“存的对象
     */
    public <T> long setCacheList(final String key, final List<T> dataList)
    {
        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
        return count == null ? 0 : count;
    public <T> boolean setCacheList(final String key, final List<T> dataList) {
        RList<T> rList = redissonClient.getList(key);
        return rList.addAll(dataList);
    }
    /**
@@ -126,9 +118,9 @@
     * @param key ç¼“存的键值
     * @return ç¼“存键值对应的数据
     */
    public <T> List<T> getCacheList(final String key)
    {
        return redisTemplate.opsForList().range(key, 0, -1);
    public <T> List<T> getCacheList(final String key) {
        RList<T> rList = redissonClient.getList(key);
        return rList.readAll();
    }
    /**
@@ -138,15 +130,9 @@
     * @param dataSet ç¼“存的数据
     * @return ç¼“存数据的对象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
    {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext())
        {
            setOperation.add(it.next());
        }
        return setOperation;
    public <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
        RSet<T> rSet = redissonClient.getSet(key);
        return rSet.addAll(dataSet);
    }
    /**
@@ -155,9 +141,9 @@
     * @param key
     * @return
     */
    public <T> Set<T> getCacheSet(final String key)
    {
        return redisTemplate.opsForSet().members(key);
    public <T> Set<T> getCacheSet(final String key) {
        RSet<T> rSet = redissonClient.getSet(key);
        return rSet.readAll();
    }
    /**
@@ -166,10 +152,10 @@
     * @param key
     * @param dataMap
     */
    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
    {
    public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
        if (dataMap != null) {
            redisTemplate.opsForHash().putAll(key, dataMap);
            RMap<String, T> rMap = redissonClient.getMap(key);
            rMap.putAll(dataMap);
        }
    }
@@ -179,9 +165,9 @@
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(final String key)
    {
        return redisTemplate.opsForHash().entries(key);
    public <T> Map<String, T> getCacheMap(final String key) {
        RMap<String, T> rMap = redissonClient.getMap(key);
        return rMap.getAll(rMap.keySet());
    }
    /**
@@ -191,9 +177,9 @@
     * @param hKey Hash键
     * @param value å€¼
     */
    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
    {
        redisTemplate.opsForHash().put(key, hKey, value);
    public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
        RMap<String, T> rMap = redissonClient.getMap(key);
        rMap.put(hKey, value);
    }
    /**
@@ -203,10 +189,9 @@
     * @param hKey Hash键
     * @return Hash中的对象
     */
    public <T> T getCacheMapValue(final String key, final String hKey)
    {
        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
        return opsForHash.get(key, hKey);
    public <T> T getCacheMapValue(final String key, final String hKey) {
        RMap<String, T> rMap = redissonClient.getMap(key);
        return rMap.get(hKey);
    }
    /**
@@ -216,9 +201,9 @@
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */
    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
    {
        return redisTemplate.opsForHash().multiGet(key, hKeys);
    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
        RListMultimap rListMultimap = redissonClient.getListMultimap(key);
        return rListMultimap.getAll(hKeys);
    }
    /**
@@ -227,8 +212,8 @@
     * @param pattern å­—符串前缀
     * @return å¯¹è±¡åˆ—表
     */
    public Collection<String> keys(final String pattern)
    {
        return redisTemplate.keys(pattern);
    public Collection<String> keys(final String pattern) {
        Iterable<String> iterable = redissonClient.getKeys().getKeysByPattern(pattern);
        return Lists.newArrayList(iterable);
    }
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/ChkjTestAddBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.ruoyi.demo.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
 * æµ‹è¯•添加对象 chkj_test
 *
 * @author Lion Li
 * @date 2021-05-14
 */
@Data
@ApiModel("测试添加对象")
public class ChkjTestAddBo {
    /** key键 */
    @ApiModelProperty("key键")
    @NotBlank(message = "key键不能为空")
    private String testKey;
    /** å€¼ */
    @ApiModelProperty("值")
    @NotBlank(message = "值不能为空")
    private String value;
    /** ç‰ˆæœ¬ */
    @ApiModelProperty("版本")
    private Long version;
    /** åˆ›å»ºæ—¶é—´ */
    @ApiModelProperty("创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /** åˆ é™¤æ ‡å¿— */
    @ApiModelProperty("删除标志")
    private Long deleted;
    /** çˆ¶id */
    @ApiModelProperty("父id")
    @NotNull(message = "父id不能为空")
    private Long parentId;
    /** æŽ’序号 */
    @ApiModelProperty("排序号")
    @NotNull(message = "排序号不能为空")
    private Long orderNum;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/ChkjTestEditBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
package com.ruoyi.demo.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
 * æµ‹è¯•编辑对象 chkj_test
 *
 * @author Lion Li
 * @date 2021-05-14
 */
@Data
@ApiModel("测试编辑对象")
public class ChkjTestEditBo {
    /** ä¸»é”® */
    @ApiModelProperty("主键")
    @NotNull(message = "主键不能为空")
    private Long id;
    /** key键 */
    @ApiModelProperty("key键")
    @NotBlank(message = "key键不能为空")
    private String testKey;
    /** å€¼ */
    @ApiModelProperty("值")
    @NotBlank(message = "值不能为空")
    private String value;
    /** ç‰ˆæœ¬ */
    @ApiModelProperty("版本")
    private Long version;
    /** åˆ›å»ºæ—¶é—´ */
    @ApiModelProperty("创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /** åˆ é™¤æ ‡å¿— */
    @ApiModelProperty("删除标志")
    private Long deleted;
    /** çˆ¶id */
    @ApiModelProperty("父id")
    @NotNull(message = "父id不能为空")
    private Long parentId;
    /** æŽ’序号 */
    @ApiModelProperty("排序号")
    @NotNull(message = "排序号不能为空")
    private Long orderNum;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/ChkjTestQueryBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
package com.ruoyi.demo.bo;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * æµ‹è¯•分页查询对象 chkj_test
 *
 * @author Lion Li
 * @date 2021-05-14
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("测试分页查询对象")
public class ChkjTestQueryBo extends BaseEntity {
    /** åˆ†é¡µå¤§å° */
    @ApiModelProperty("分页大小")
    private Integer pageSize;
    /** å½“前页数 */
    @ApiModelProperty("当前页数")
    private Integer pageNum;
    /** æŽ’序列 */
    @ApiModelProperty("排序列")
    private String orderByColumn;
    /** æŽ’序的方向desc或者asc */
    @ApiModelProperty(value = "排序的方向", example = "asc,desc")
    private String isAsc;
    /** key键 */
    @ApiModelProperty("key键")
    private String testKey;
    /** å€¼ */
    @ApiModelProperty("值")
    private String value;
    /** ç‰ˆæœ¬ */
    @ApiModelProperty("版本")
    private Long version;
    /** åˆ é™¤æ ‡å¿— */
    @ApiModelProperty("删除标志")
    private Long deleted;
    /** çˆ¶id */
    @ApiModelProperty("父id")
    private Long parentId;
    /** æŽ’序号 */
    @ApiModelProperty("排序号")
    private Long orderNum;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestDemoAddBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
package com.ruoyi.demo.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
 * æµ‹è¯•单表添加对象 test_demo
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@ApiModel("测试单表添加对象")
public class TestDemoAddBo {
    /** éƒ¨é—¨id */
    @ApiModelProperty("部门id")
    private Long deptId;
    /** ç”¨æˆ·id */
    @ApiModelProperty("用户id")
    private Long userId;
    /** æŽ’序号 */
    @ApiModelProperty("排序号")
    private Long orderNum;
    /** key键 */
    @ApiModelProperty("key键")
    @NotBlank(message = "key键不能为空")
    private String testKey;
    /** å€¼ */
    @ApiModelProperty("值")
    @NotBlank(message = "值不能为空")
    private String value;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestDemoEditBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.ruoyi.demo.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
 * æµ‹è¯•单表编辑对象 test_demo
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@ApiModel("测试单表编辑对象")
public class TestDemoEditBo {
    /** ä¸»é”® */
    @ApiModelProperty("主键")
    private Long id;
    /** éƒ¨é—¨id */
    @ApiModelProperty("部门id")
    private Long deptId;
    /** ç”¨æˆ·id */
    @ApiModelProperty("用户id")
    private Long userId;
    /** æŽ’序号 */
    @ApiModelProperty("排序号")
    private Long orderNum;
    /** key键 */
    @ApiModelProperty("key键")
    @NotBlank(message = "key键不能为空")
    private String testKey;
    /** å€¼ */
    @ApiModelProperty("值")
    @NotBlank(message = "值不能为空")
    private String value;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestDemoQueryBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package com.ruoyi.demo.bo;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * æµ‹è¯•单表分页查询对象 test_demo
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("测试单表分页查询对象")
public class TestDemoQueryBo extends BaseEntity {
    /** åˆ†é¡µå¤§å° */
    @ApiModelProperty("分页大小")
    private Integer pageSize;
    /** å½“前页数 */
    @ApiModelProperty("当前页数")
    private Integer pageNum;
    /** æŽ’序列 */
    @ApiModelProperty("排序列")
    private String orderByColumn;
    /** æŽ’序的方向desc或者asc */
    @ApiModelProperty(value = "排序的方向", example = "asc,desc")
    private String isAsc;
    /** key键 */
    @ApiModelProperty("key键")
    private String testKey;
    /** å€¼ */
    @ApiModelProperty("值")
    private String value;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestTreeAddBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.ruoyi.demo.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
import javax.validation.constraints.*;
/**
 * æµ‹è¯•树表添加对象 test_tree
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@ApiModel("测试树表添加对象")
public class TestTreeAddBo {
    /** çˆ¶id */
    @ApiModelProperty("父id")
    private Long parentId;
    /** éƒ¨é—¨id */
    @ApiModelProperty("部门id")
    private Long deptId;
    /** ç”¨æˆ·id */
    @ApiModelProperty("用户id")
    private Long userId;
    /** æ ‘节点名 */
    @ApiModelProperty("树节点名")
    @NotBlank(message = "树节点名不能为空")
    private String treeName;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestTreeEditBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package com.ruoyi.demo.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
import javax.validation.constraints.*;
/**
 * æµ‹è¯•树表编辑对象 test_tree
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@ApiModel("测试树表编辑对象")
public class TestTreeEditBo {
    /** ä¸»é”® */
    @ApiModelProperty("主键")
    private Long id;
    /** çˆ¶id */
    @ApiModelProperty("父id")
    private Long parentId;
    /** éƒ¨é—¨id */
    @ApiModelProperty("部门id")
    private Long deptId;
    /** ç”¨æˆ·id */
    @ApiModelProperty("用户id")
    private Long userId;
    /** æ ‘节点名 */
    @ApiModelProperty("树节点名")
    @NotBlank(message = "树节点名不能为空")
    private String treeName;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/bo/TestTreeQueryBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package com.ruoyi.demo.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.ruoyi.common.core.domain.BaseEntity;
/**
 * æµ‹è¯•树表分页查询对象 test_tree
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("测试树表分页查询对象")
public class TestTreeQueryBo extends BaseEntity {
    /** åˆ†é¡µå¤§å° */
    @ApiModelProperty("分页大小")
    private Integer pageSize;
    /** å½“前页数 */
    @ApiModelProperty("当前页数")
    private Integer pageNum;
    /** æŽ’序列 */
    @ApiModelProperty("排序列")
    private String orderByColumn;
    /** æŽ’序的方向desc或者asc */
    @ApiModelProperty(value = "排序的方向", example = "asc,desc")
    private String isAsc;
    /** æ ‘节点名 */
    @ApiModelProperty("树节点名")
    private String treeName;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/ChkjTestController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,108 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.demo.bo.ChkjTestAddBo;
import com.ruoyi.demo.bo.ChkjTestEditBo;
import com.ruoyi.demo.bo.ChkjTestQueryBo;
import com.ruoyi.demo.service.IChkjTestService;
import com.ruoyi.demo.vo.ChkjTestVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
/**
 * æµ‹è¯•Controller
 *
 * @author Lion Li
 * @date 2021-05-14
 */
@Api(value = "测试控制器", tags = {"测试管理"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/demo/test")
public class ChkjTestController extends BaseController {
    private final IChkjTestService iChkjTestService;
    /**
     * æŸ¥è¯¢æµ‹è¯•列表
     */
    @ApiOperation("查询测试列表")
    @PreAuthorize("@ss.hasPermi('demo:test:list')")
    @GetMapping("/list")
    public TableDataInfo<ChkjTestVo> list(@Validated ChkjTestQueryBo bo) {
        return iChkjTestService.queryPageList(bo);
    }
    /**
     * å¯¼å‡ºæµ‹è¯•列表
     */
    @ApiOperation("导出测试列表")
    @PreAuthorize("@ss.hasPermi('demo:test:export')")
    @Log(title = "测试", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult<ChkjTestVo> export(@Validated ChkjTestQueryBo bo) {
        List<ChkjTestVo> list = iChkjTestService.queryList(bo);
        ExcelUtil<ChkjTestVo> util = new ExcelUtil<ChkjTestVo>(ChkjTestVo.class);
        return util.exportExcel(list, "测试");
    }
    /**
     * èŽ·å–æµ‹è¯•è¯¦ç»†ä¿¡æ¯
     */
    @ApiOperation("获取测试详细信息")
    @PreAuthorize("@ss.hasPermi('demo:test:query')")
    @GetMapping("/{id}")
    public AjaxResult<ChkjTestVo> getInfo(@NotNull(message = "主键不能为空")
                                                  @PathVariable("id") Long id) {
        return AjaxResult.success(iChkjTestService.queryById(id));
    }
    /**
     * æ–°å¢žæµ‹è¯•
     */
    @ApiOperation("新增测试")
    @PreAuthorize("@ss.hasPermi('demo:test:add')")
    @Log(title = "测试", businessType = BusinessType.INSERT)
    @PostMapping()
    public AjaxResult<Void> add(@Validated @RequestBody ChkjTestAddBo bo) {
        return toAjax(iChkjTestService.insertByAddBo(bo) ? 1 : 0);
    }
    /**
     * ä¿®æ”¹æµ‹è¯•
     */
    @ApiOperation("修改测试")
    @PreAuthorize("@ss.hasPermi('demo:test:edit')")
    @Log(title = "测试", businessType = BusinessType.UPDATE)
    @PutMapping()
    public AjaxResult<Void> edit(@Validated @RequestBody ChkjTestEditBo bo) {
        return toAjax(iChkjTestService.updateByEditBo(bo) ? 1 : 0);
    }
    /**
     * åˆ é™¤æµ‹è¯•
     */
    @ApiOperation("删除测试")
    @PreAuthorize("@ss.hasPermi('demo:test:remove')")
    @Log(title = "测试" , businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
                                       @PathVariable Long[] ids) {
        return toAjax(iChkjTestService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
    }
}
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,108 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.demo.bo.TestDemoAddBo;
import com.ruoyi.demo.bo.TestDemoEditBo;
import com.ruoyi.demo.bo.TestDemoQueryBo;
import com.ruoyi.demo.service.ITestDemoService;
import com.ruoyi.demo.vo.TestDemoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
/**
 * æµ‹è¯•单表Controller
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Api(value = "测试单表控制器", tags = {"测试单表管理"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/demo/demo")
public class TestDemoController extends BaseController {
    private final ITestDemoService iTestDemoService;
    /**
     * æŸ¥è¯¢æµ‹è¯•单表列表
     */
    @ApiOperation("查询测试单表列表")
    @PreAuthorize("@ss.hasPermi('demo:demo:list')")
    @GetMapping("/list")
    public TableDataInfo<TestDemoVo> list(@Validated TestDemoQueryBo bo) {
        return iTestDemoService.queryPageList(bo);
    }
    /**
     * å¯¼å‡ºæµ‹è¯•单表列表
     */
    @ApiOperation("导出测试单表列表")
    @PreAuthorize("@ss.hasPermi('demo:demo:export')")
    @Log(title = "测试单表", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult<TestDemoVo> export(@Validated TestDemoQueryBo bo) {
        List<TestDemoVo> list = iTestDemoService.queryList(bo);
        ExcelUtil<TestDemoVo> util = new ExcelUtil<TestDemoVo>(TestDemoVo.class);
        return util.exportExcel(list, "测试单表");
    }
    /**
     * èŽ·å–æµ‹è¯•å•è¡¨è¯¦ç»†ä¿¡æ¯
     */
    @ApiOperation("获取测试单表详细信息")
    @PreAuthorize("@ss.hasPermi('demo:demo:query')")
    @GetMapping("/{id}")
    public AjaxResult<TestDemoVo> getInfo(@NotNull(message = "主键不能为空")
                                                  @PathVariable("id") Long id) {
        return AjaxResult.success(iTestDemoService.queryById(id));
    }
    /**
     * æ–°å¢žæµ‹è¯•单表
     */
    @ApiOperation("新增测试单表")
    @PreAuthorize("@ss.hasPermi('demo:demo:add')")
    @Log(title = "测试单表", businessType = BusinessType.INSERT)
    @PostMapping()
    public AjaxResult<Void> add(@Validated @RequestBody TestDemoAddBo bo) {
        return toAjax(iTestDemoService.insertByAddBo(bo) ? 1 : 0);
    }
    /**
     * ä¿®æ”¹æµ‹è¯•单表
     */
    @ApiOperation("修改测试单表")
    @PreAuthorize("@ss.hasPermi('demo:demo:edit')")
    @Log(title = "测试单表", businessType = BusinessType.UPDATE)
    @PutMapping()
    public AjaxResult<Void> edit(@Validated @RequestBody TestDemoEditBo bo) {
        return toAjax(iTestDemoService.updateByEditBo(bo) ? 1 : 0);
    }
    /**
     * åˆ é™¤æµ‹è¯•单表
     */
    @ApiOperation("删除测试单表")
    @PreAuthorize("@ss.hasPermi('demo:demo:remove')")
    @Log(title = "测试单表" , businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
                                       @PathVariable Long[] ids) {
        return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
    }
}
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,107 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.demo.bo.TestTreeAddBo;
import com.ruoyi.demo.bo.TestTreeEditBo;
import com.ruoyi.demo.bo.TestTreeQueryBo;
import com.ruoyi.demo.service.ITestTreeService;
import com.ruoyi.demo.vo.TestTreeVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
/**
 * æµ‹è¯•树表Controller
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Api(value = "测试树表控制器", tags = {"测试树表管理"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/demo/tree")
public class TestTreeController extends BaseController {
    private final ITestTreeService iTestTreeService;
    /**
     * æŸ¥è¯¢æµ‹è¯•树表列表
     */
    @ApiOperation("查询测试树表列表")
    @PreAuthorize("@ss.hasPermi('demo:tree:list')")
    @GetMapping("/list")
    public AjaxResult<List<TestTreeVo>> list(@Validated TestTreeQueryBo bo) {
        return AjaxResult.success(iTestTreeService.queryList(bo));
    }
    /**
     * å¯¼å‡ºæµ‹è¯•树表列表
     */
    @ApiOperation("导出测试树表列表")
    @PreAuthorize("@ss.hasPermi('demo:tree:export')")
    @Log(title = "测试树表", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult<TestTreeVo> export(@Validated TestTreeQueryBo bo) {
        List<TestTreeVo> list = iTestTreeService.queryList(bo);
        ExcelUtil<TestTreeVo> util = new ExcelUtil<TestTreeVo>(TestTreeVo.class);
        return util.exportExcel(list, "测试树表");
    }
    /**
     * èŽ·å–æµ‹è¯•æ ‘è¡¨è¯¦ç»†ä¿¡æ¯
     */
    @ApiOperation("获取测试树表详细信息")
    @PreAuthorize("@ss.hasPermi('demo:tree:query')")
    @GetMapping("/{id}")
    public AjaxResult<TestTreeVo> getInfo(@NotNull(message = "主键不能为空")
                                                  @PathVariable("id") Long id) {
        return AjaxResult.success(iTestTreeService.queryById(id));
    }
    /**
     * æ–°å¢žæµ‹è¯•树表
     */
    @ApiOperation("新增测试树表")
    @PreAuthorize("@ss.hasPermi('demo:tree:add')")
    @Log(title = "测试树表", businessType = BusinessType.INSERT)
    @PostMapping()
    public AjaxResult<Void> add(@Validated @RequestBody TestTreeAddBo bo) {
        return toAjax(iTestTreeService.insertByAddBo(bo) ? 1 : 0);
    }
    /**
     * ä¿®æ”¹æµ‹è¯•树表
     */
    @ApiOperation("修改测试树表")
    @PreAuthorize("@ss.hasPermi('demo:tree:edit')")
    @Log(title = "测试树表", businessType = BusinessType.UPDATE)
    @PutMapping()
    public AjaxResult<Void> edit(@Validated @RequestBody TestTreeEditBo bo) {
        return toAjax(iTestTreeService.updateByEditBo(bo) ? 1 : 0);
    }
    /**
     * åˆ é™¤æµ‹è¯•树表
     */
    @ApiOperation("删除测试树表")
    @PreAuthorize("@ss.hasPermi('demo:tree:remove')")
    @Log(title = "测试树表" , businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
                                       @PathVariable Long[] ids) {
        return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
    }
}
ruoyi-demo/src/main/java/com/ruoyi/demo/domain/ChkjTest.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.ruoyi.demo.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
 * æµ‹è¯•对象 chkj_test
 *
 * @author Lion Li
 * @date 2021-05-14
 */
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("chkj_test")
public class ChkjTest implements Serializable {
private static final long serialVersionUID=1L;
    /** ä¸»é”® */
    @TableId(value = "id")
    private Long id;
    /** key键 */
    private String testKey;
    /** å€¼ */
    private String value;
    /** ç‰ˆæœ¬ */
    private Long version;
    /** åˆ›å»ºæ—¶é—´ */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    /** åˆ é™¤æ ‡å¿— */
    private Long deleted;
    /** çˆ¶id */
    private Long parentId;
    /** æŽ’序号 */
    private Long orderNum;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
package com.ruoyi.demo.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
 * æµ‹è¯•单表对象 test_demo
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("test_demo")
public class TestDemo implements Serializable {
    private static final long serialVersionUID=1L;
    /** ä¸»é”® */
    @TableId(value = "id")
    private Long id;
    /** éƒ¨é—¨id */
    private Long deptId;
    /** ç”¨æˆ·id */
    private Long userId;
    /** æŽ’序号 */
    @OrderBy(isDesc = false, sort = 1)
    private Long orderNum;
    /** key键 */
    private String testKey;
    /** å€¼ */
    private String value;
    /** ç‰ˆæœ¬ */
    @Version
    private Long version;
    /** åˆ›å»ºæ—¶é—´ */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    /** åˆ›å»ºäºº */
    @TableField(fill = FieldFill.INSERT)
    private String createBy;
    /** æ›´æ–°æ—¶é—´ */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    /** æ›´æ–°äºº */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateBy;
    /** åˆ é™¤æ ‡å¿— */
    @TableLogic
    private Long delFlag;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
package com.ruoyi.demo.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.ruoyi.common.annotation.Excel;
/**
 * æµ‹è¯•树表对象 test_tree
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("test_tree")
public class TestTree implements Serializable {
    private static final long serialVersionUID=1L;
    /** ä¸»é”® */
    @TableId(value = "id")
    private Long id;
    /** çˆ¶id */
    private Long parentId;
    /** éƒ¨é—¨id */
    private Long deptId;
    /** ç”¨æˆ·id */
    private Long userId;
    /** æ ‘节点名 */
    private String treeName;
    /** ç‰ˆæœ¬ */
    @Version
    private Long version;
    /** åˆ›å»ºæ—¶é—´ */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    /** åˆ›å»ºäºº */
    @TableField(fill = FieldFill.INSERT)
    private String createBy;
    /** æ›´æ–°æ—¶é—´ */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    /** æ›´æ–°äºº */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateBy;
    /** åˆ é™¤æ ‡å¿— */
    @TableLogic
    private Long delFlag;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/ChkjTestMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.ruoyi.demo.mapper;
import com.ruoyi.demo.domain.ChkjTest;
import com.ruoyi.common.core.page.BaseMapperPlus;
/**
 * æµ‹è¯•Mapper接口
 *
 * @author Lion Li
 * @date 2021-05-14
 */
public interface ChkjTestMapper extends BaseMapperPlus<ChkjTest> {
}
ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.ruoyi.demo.mapper;
import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.common.core.page.BaseMapperPlus;
/**
 * æµ‹è¯•单表Mapper接口
 *
 * @author Lion Li
 * @date 2021-05-30
 */
public interface TestDemoMapper extends BaseMapperPlus<TestDemo> {
}
ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.ruoyi.demo.mapper;
import com.ruoyi.demo.domain.TestTree;
import com.ruoyi.common.core.page.BaseMapperPlus;
/**
 * æµ‹è¯•树表Mapper接口
 *
 * @author Lion Li
 * @date 2021-05-30
 */
public interface TestTreeMapper extends BaseMapperPlus<TestTree> {
}
ruoyi-demo/src/main/java/com/ruoyi/demo/service/IChkjTestService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
package com.ruoyi.demo.service;
import com.ruoyi.demo.domain.ChkjTest;
import com.ruoyi.demo.vo.ChkjTestVo;
import com.ruoyi.demo.bo.ChkjTestQueryBo;
import com.ruoyi.demo.bo.ChkjTestAddBo;
import com.ruoyi.demo.bo.ChkjTestEditBo;
import com.ruoyi.common.core.page.IServicePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import java.util.Collection;
import java.util.List;
/**
 * æµ‹è¯•Service接口
 *
 * @author Lion Li
 * @date 2021-05-14
 */
public interface IChkjTestService extends IServicePlus<ChkjTest> {
    /**
     * æŸ¥è¯¢å•个
     * @return
     */
    ChkjTestVo queryById(Long id);
    /**
     * æŸ¥è¯¢åˆ—表
     */
    TableDataInfo<ChkjTestVo> queryPageList(ChkjTestQueryBo bo);
    /**
     * æŸ¥è¯¢åˆ—表
     */
    List<ChkjTestVo> queryList(ChkjTestQueryBo bo);
    /**
     * æ ¹æ®æ–°å¢žä¸šåŠ¡å¯¹è±¡æ’å…¥æµ‹è¯•
     * @param bo æµ‹è¯•新增业务对象
     * @return
     */
    Boolean insertByAddBo(ChkjTestAddBo bo);
    /**
     * æ ¹æ®ç¼–辑业务对象修改测试
     * @param bo æµ‹è¯•编辑业务对象
     * @return
     */
    Boolean updateByEditBo(ChkjTestEditBo bo);
    /**
     * æ ¡éªŒå¹¶åˆ é™¤æ•°æ®
     * @param ids ä¸»é”®é›†åˆ
     * @param isValid æ˜¯å¦æ ¡éªŒ,true-删除前校验,false-不校验
     * @return
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}
ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
package com.ruoyi.demo.service;
import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.demo.vo.TestDemoVo;
import com.ruoyi.demo.bo.TestDemoQueryBo;
import com.ruoyi.demo.bo.TestDemoAddBo;
import com.ruoyi.demo.bo.TestDemoEditBo;
import com.ruoyi.common.core.page.IServicePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import java.util.Collection;
import java.util.List;
/**
 * æµ‹è¯•单表Service接口
 *
 * @author Lion Li
 * @date 2021-05-30
 */
public interface ITestDemoService extends IServicePlus<TestDemo> {
    /**
     * æŸ¥è¯¢å•个
     * @return
     */
    TestDemoVo queryById(Long id);
    /**
     * æŸ¥è¯¢åˆ—表
     */
    TableDataInfo<TestDemoVo> queryPageList(TestDemoQueryBo bo);
    /**
     * æŸ¥è¯¢åˆ—表
     */
    List<TestDemoVo> queryList(TestDemoQueryBo bo);
    /**
     * æ ¹æ®æ–°å¢žä¸šåŠ¡å¯¹è±¡æ’å…¥æµ‹è¯•å•è¡¨
     * @param bo æµ‹è¯•单表新增业务对象
     * @return
     */
    Boolean insertByAddBo(TestDemoAddBo bo);
    /**
     * æ ¹æ®ç¼–辑业务对象修改测试单表
     * @param bo æµ‹è¯•单表编辑业务对象
     * @return
     */
    Boolean updateByEditBo(TestDemoEditBo bo);
    /**
     * æ ¡éªŒå¹¶åˆ é™¤æ•°æ®
     * @param ids ä¸»é”®é›†åˆ
     * @param isValid æ˜¯å¦æ ¡éªŒ,true-删除前校验,false-不校验
     * @return
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}
ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestTreeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.ruoyi.demo.service;
import com.ruoyi.common.core.page.IServicePlus;
import com.ruoyi.demo.bo.TestTreeAddBo;
import com.ruoyi.demo.bo.TestTreeEditBo;
import com.ruoyi.demo.bo.TestTreeQueryBo;
import com.ruoyi.demo.domain.TestTree;
import com.ruoyi.demo.vo.TestTreeVo;
import java.util.Collection;
import java.util.List;
/**
 * æµ‹è¯•树表Service接口
 *
 * @author Lion Li
 * @date 2021-05-30
 */
public interface ITestTreeService extends IServicePlus<TestTree> {
    /**
     * æŸ¥è¯¢å•个
     * @return
     */
    TestTreeVo queryById(Long id);
    /**
     * æŸ¥è¯¢åˆ—表
     */
    List<TestTreeVo> queryList(TestTreeQueryBo bo);
    /**
     * æ ¹æ®æ–°å¢žä¸šåŠ¡å¯¹è±¡æ’å…¥æµ‹è¯•æ ‘è¡¨
     * @param bo æµ‹è¯•树表新增业务对象
     * @return
     */
    Boolean insertByAddBo(TestTreeAddBo bo);
    /**
     * æ ¹æ®ç¼–辑业务对象修改测试树表
     * @param bo æµ‹è¯•树表编辑业务对象
     * @return
     */
    Boolean updateByEditBo(TestTreeEditBo bo);
    /**
     * æ ¡éªŒå¹¶åˆ é™¤æ•°æ®
     * @param ids ä¸»é”®é›†åˆ
     * @param isValid æ˜¯å¦æ ¡éªŒ,true-删除前校验,false-不校验
     * @return
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}
ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/ChkjTestServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,93 @@
package com.ruoyi.demo.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.demo.bo.ChkjTestAddBo;
import com.ruoyi.demo.bo.ChkjTestEditBo;
import com.ruoyi.demo.bo.ChkjTestQueryBo;
import com.ruoyi.demo.domain.ChkjTest;
import com.ruoyi.demo.mapper.ChkjTestMapper;
import com.ruoyi.demo.service.IChkjTestService;
import com.ruoyi.demo.vo.ChkjTestVo;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
 * æµ‹è¯•Service业务层处理
 *
 * @author Lion Li
 * @date 2021-05-14
 */
@Service
public class ChkjTestServiceImpl extends ServiceImpl<ChkjTestMapper, ChkjTest> implements IChkjTestService {
    @Override
    public ChkjTestVo queryById(Long id){
        return getVoById(id, obj -> BeanUtil.toBean(obj, ChkjTestVo.class));
    }
    @Override
    public TableDataInfo<ChkjTestVo> queryPageList(ChkjTestQueryBo bo) {
        PagePlus<ChkjTest, ChkjTestVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), ChkjTestVo.class);
        return PageUtils.buildDataInfo(result);
    }
    @Override
    public List<ChkjTestVo> queryList(ChkjTestQueryBo bo) {
        return listVo(buildQueryWrapper(bo), ChkjTestVo.class);
    }
    private LambdaQueryWrapper<ChkjTest> buildQueryWrapper(ChkjTestQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ChkjTest> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(bo.getTestKey()), ChkjTest::getTestKey, bo.getTestKey());
        lqw.eq(StrUtil.isNotBlank(bo.getValue()), ChkjTest::getValue, bo.getValue());
        lqw.eq(bo.getVersion() != null, ChkjTest::getVersion, bo.getVersion());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            ChkjTest::getCreateTime ,params.get("beginCreateTime"), params.get("endCreateTime"));
        lqw.eq(bo.getDeleted() != null, ChkjTest::getDeleted, bo.getDeleted());
        lqw.eq(bo.getParentId() != null, ChkjTest::getParentId, bo.getParentId());
        lqw.eq(bo.getOrderNum() != null, ChkjTest::getOrderNum, bo.getOrderNum());
        return lqw;
    }
    @Override
    public Boolean insertByAddBo(ChkjTestAddBo bo) {
        ChkjTest add = BeanUtil.toBean(bo, ChkjTest.class);
        validEntityBeforeSave(add);
        return save(add);
    }
    @Override
    public Boolean updateByEditBo(ChkjTestEditBo bo) {
        ChkjTest update = BeanUtil.toBean(bo, ChkjTest.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     *
     * @param entity å®žä½“类数据
     */
    private void validEntityBeforeSave(ChkjTest entity){
        //TODO åšä¸€äº›æ•°æ®æ ¡éªŒ,如唯一约束
    }
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO åšä¸€äº›ä¸šåŠ¡ä¸Šçš„æ ¡éªŒ,判断是否需要校验
        }
        return removeByIds(ids);
    }
}
ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,95 @@
package com.ruoyi.demo.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.demo.bo.TestDemoAddBo;
import com.ruoyi.demo.bo.TestDemoEditBo;
import com.ruoyi.demo.bo.TestDemoQueryBo;
import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.demo.mapper.TestDemoMapper;
import com.ruoyi.demo.service.ITestDemoService;
import com.ruoyi.demo.vo.TestDemoVo;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
 * æµ‹è¯•单表Service业务层处理
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Service
public class TestDemoServiceImpl extends ServiceImpl<TestDemoMapper, TestDemo> implements ITestDemoService {
    @Override
    public TestDemoVo queryById(Long id) {
        return getVoById(id, TestDemoVo.class);
    }
    @DataScope(isUser = true)
    @Override
    public TableDataInfo<TestDemoVo> queryPageList(TestDemoQueryBo bo) {
        PagePlus<TestDemo, TestDemoVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), TestDemoVo.class);
        return PageUtils.buildDataInfo(result);
    }
    @DataScope(isUser = true)
    @Override
    public List<TestDemoVo> queryList(TestDemoQueryBo bo) {
        return listVo(buildQueryWrapper(bo), TestDemoVo.class);
    }
    private LambdaQueryWrapper<TestDemo> buildQueryWrapper(TestDemoQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        Object dataScope = params.get("dataScope");
        LambdaQueryWrapper<TestDemo> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey());
        lqw.eq(StrUtil.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            TestDemo::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
        lqw.apply(dataScope != null && StrUtil.isNotBlank(dataScope.toString()),
            dataScope != null ? dataScope.toString() : null);
        return lqw;
    }
    @Override
    public Boolean insertByAddBo(TestDemoAddBo bo) {
        TestDemo add = BeanUtil.toBean(bo, TestDemo.class);
        validEntityBeforeSave(add);
        return save(add);
    }
    @Override
    public Boolean updateByEditBo(TestDemoEditBo bo) {
        TestDemo update = BeanUtil.toBean(bo, TestDemo.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     *
     * @param entity å®žä½“类数据
     */
    private void validEntityBeforeSave(TestDemo entity) {
        //TODO åšä¸€äº›æ•°æ®æ ¡éªŒ,如唯一约束
    }
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO åšä¸€äº›ä¸šåŠ¡ä¸Šçš„æ ¡éªŒ,判断是否需要校验
        }
        return removeByIds(ids);
    }
}
ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
package com.ruoyi.demo.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.demo.bo.TestTreeAddBo;
import com.ruoyi.demo.bo.TestTreeEditBo;
import com.ruoyi.demo.bo.TestTreeQueryBo;
import com.ruoyi.demo.domain.TestTree;
import com.ruoyi.demo.mapper.TestTreeMapper;
import com.ruoyi.demo.service.ITestTreeService;
import com.ruoyi.demo.vo.TestTreeVo;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
 * æµ‹è¯•树表Service业务层处理
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Service
public class TestTreeServiceImpl extends ServiceImpl<TestTreeMapper, TestTree> implements ITestTreeService {
    @Override
    public TestTreeVo queryById(Long id) {
        return getVoById(id, TestTreeVo.class);
    }
    @DataScope(isUser = true)
    @Override
    public List<TestTreeVo> queryList(TestTreeQueryBo bo) {
        return listVo(buildQueryWrapper(bo), TestTreeVo.class);
    }
    private LambdaQueryWrapper<TestTree> buildQueryWrapper(TestTreeQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        Object dataScope = params.get("dataScope");
        LambdaQueryWrapper<TestTree> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            TestTree::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
        lqw.apply(dataScope != null && StrUtil.isNotBlank(dataScope.toString()),
            dataScope != null ? dataScope.toString() : null);
        return lqw;
    }
    @Override
    public Boolean insertByAddBo(TestTreeAddBo bo) {
        TestTree add = BeanUtil.toBean(bo, TestTree.class);
        validEntityBeforeSave(add);
        return save(add);
    }
    @Override
    public Boolean updateByEditBo(TestTreeEditBo bo) {
        TestTree update = BeanUtil.toBean(bo, TestTree.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     *
     * @param entity å®žä½“类数据
     */
    private void validEntityBeforeSave(TestTree entity) {
        //TODO åšä¸€äº›æ•°æ®æ ¡éªŒ,如唯一约束
    }
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO åšä¸€äº›ä¸šåŠ¡ä¸Šçš„æ ¡éªŒ,判断是否需要校验
        }
        return removeByIds(ids);
    }
}
ruoyi-demo/src/main/java/com/ruoyi/demo/vo/ChkjTestVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
package com.ruoyi.demo.vo;
import com.ruoyi.common.annotation.Excel;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * æµ‹è¯•视图对象 mall_package
 *
 * @author Lion Li
 * @date 2021-05-14
 */
@Data
@ApiModel("测试视图对象")
public class ChkjTestVo {
    private static final long serialVersionUID = 1L;
    /** ä¸»é”® */
    @ApiModelProperty("主键")
    private Long id;
    /** key键 */
    @Excel(name = "key键")
    @ApiModelProperty("key键")
    private String testKey;
    /** å€¼ */
    @Excel(name = "值")
    @ApiModelProperty("值")
    private String value;
    /** ç‰ˆæœ¬ */
    @Excel(name = "版本")
    @ApiModelProperty("版本")
    private Long version;
    /** åˆ›å»ºæ—¶é—´ */
    @Excel(name = "创建时间" , width = 30, dateFormat = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty("创建时间")
    private Date createTime;
    /** åˆ é™¤æ ‡å¿— */
    @Excel(name = "删除标志")
    @ApiModelProperty("删除标志")
    private Long deleted;
    /** çˆ¶id */
    @Excel(name = "父id")
    @ApiModelProperty("父id")
    private Long parentId;
    /** æŽ’序号 */
    @Excel(name = "排序号")
    @ApiModelProperty("排序号")
    private Long orderNum;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/vo/TestDemoVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package com.ruoyi.demo.vo;
import com.ruoyi.common.annotation.Excel;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * æµ‹è¯•单表视图对象 test_demo
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@ApiModel("测试单表视图对象")
public class TestDemoVo {
    private static final long serialVersionUID = 1L;
    /** ä¸»é”® */
    @ApiModelProperty("主键")
    private Long id;
    /** éƒ¨é—¨id */
    @Excel(name = "部门id")
    @ApiModelProperty("部门id")
    private Long deptId;
    /** ç”¨æˆ·id */
    @Excel(name = "用户id")
    @ApiModelProperty("用户id")
    private Long userId;
    /** æŽ’序号 */
    @Excel(name = "排序号")
    @ApiModelProperty("排序号")
    private Long orderNum;
    /** key键 */
    @Excel(name = "key键")
    @ApiModelProperty("key键")
    private String testKey;
    /** å€¼ */
    @Excel(name = "值")
    @ApiModelProperty("值")
    private String value;
    /** åˆ›å»ºæ—¶é—´ */
    @Excel(name = "创建时间" , width = 30, dateFormat = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty("创建时间")
    private Date createTime;
    /** åˆ›å»ºäºº */
    @Excel(name = "创建人")
    @ApiModelProperty("创建人")
    private String createBy;
    /** æ›´æ–°æ—¶é—´ */
    @Excel(name = "更新时间" , width = 30, dateFormat = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty("更新时间")
    private Date updateTime;
    /** æ›´æ–°äºº */
    @Excel(name = "更新人")
    @ApiModelProperty("更新人")
    private String updateBy;
}
ruoyi-demo/src/main/java/com/ruoyi/demo/vo/TestTreeVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.ruoyi.demo.vo;
import com.ruoyi.common.annotation.Excel;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * æµ‹è¯•树表视图对象 test_tree
 *
 * @author Lion Li
 * @date 2021-05-30
 */
@Data
@ApiModel("测试树表视图对象")
public class TestTreeVo {
    private static final long serialVersionUID = 1L;
    /** ä¸»é”® */
    @ApiModelProperty("主键")
    private Long id;
    /** çˆ¶id */
    @Excel(name = "父id")
    @ApiModelProperty("父id")
    private Long parentId;
    /** éƒ¨é—¨id */
    @Excel(name = "部门id")
    @ApiModelProperty("部门id")
    private Long deptId;
    /** ç”¨æˆ·id */
    @Excel(name = "用户id")
    @ApiModelProperty("用户id")
    private Long userId;
    /** æ ‘节点名 */
    @Excel(name = "树节点名")
    @ApiModelProperty("树节点名")
    private String treeName;
    /** åˆ›å»ºæ—¶é—´ */
    @Excel(name = "创建时间" , width = 30, dateFormat = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty("创建时间")
    private Date createTime;
}
ruoyi-demo/src/main/resources/mapper/demo/ChkjTestMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.demo.mapper.ChkjTestMapper">
    <resultMap type="com.ruoyi.demo.domain.ChkjTest" id="ChkjTestResult">
        <result property="id" column="id"/>
        <result property="testKey" column="test_key"/>
        <result property="value" column="value"/>
        <result property="version" column="version"/>
        <result property="createTime" column="create_time"/>
        <result property="deleted" column="deleted"/>
        <result property="parentId" column="parent_id"/>
        <result property="orderNum" column="order_num"/>
    </resultMap>
</mapper>
ruoyi-demo/src/main/resources/mapper/demo/TestDemoMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.demo.mapper.TestDemoMapper">
    <resultMap type="com.ruoyi.demo.domain.TestDemo" id="TestDemoResult">
        <result property="id" column="id"/>
        <result property="deptId" column="dept_id"/>
        <result property="userId" column="user_id"/>
        <result property="orderNum" column="order_num"/>
        <result property="testKey" column="test_key"/>
        <result property="value" column="value"/>
        <result property="version" column="version"/>
        <result property="createTime" column="create_time"/>
        <result property="createBy" column="create_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="delFlag" column="del_flag"/>
    </resultMap>
</mapper>
ruoyi-demo/src/main/resources/mapper/demo/TestTreeMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.demo.mapper.TestTreeMapper">
    <resultMap type="com.ruoyi.demo.domain.TestTree" id="TestTreeResult">
        <result property="id" column="id"/>
        <result property="parentId" column="parent_id"/>
        <result property="deptId" column="dept_id"/>
        <result property="userId" column="user_id"/>
        <result property="treeName" column="tree_name"/>
        <result property="version" column="version"/>
        <result property="createTime" column="create_time"/>
        <result property="createBy" column="create_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="delFlag" column="del_flag"/>
    </resultMap>
</mapper>
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
@@ -24,12 +24,12 @@
/**
 * æ•°æ®è¿‡æ»¤å¤„理
 *
 * @author ruoyi
 * @author Lion Li
 */
@Aspect
@Component
public class DataScopeAspect
{
public class DataScopeAspect {
    /**
     * å…¨éƒ¨æ•°æ®æƒé™
     */
@@ -62,35 +62,29 @@
    // é…ç½®ç»‡å…¥ç‚¹
    @Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)")
    public void dataScopePointCut()
    {
    public void dataScopePointCut() {
    }
    @Before("dataScopePointCut()")
    public void doBefore(JoinPoint point) throws Throwable
    {
    public void doBefore(JoinPoint point) throws Throwable {
        clearDataScope(point);
        handleDataScope(point);
    }
    protected void handleDataScope(final JoinPoint joinPoint)
    {
    protected void handleDataScope(final JoinPoint joinPoint) {
        // èŽ·å¾—æ³¨è§£
        DataScope controllerDataScope = getAnnotationLog(joinPoint);
        if (controllerDataScope == null)
        {
        if (controllerDataScope == null) {
            return;
        }
        // èŽ·å–å½“å‰çš„ç”¨æˆ·
        LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
        if (Validator.isNotNull(loginUser))
        {
        if (Validator.isNotNull(loginUser)) {
            SysUser currentUser = loginUser.getUser();
            // å¦‚果是超级管理员,则不过滤数据
            if (Validator.isNotNull(currentUser) && !currentUser.isAdmin())
            {
            if (Validator.isNotNull(currentUser) && !currentUser.isAdmin()) {
                dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
                        controllerDataScope.userAlias());
                    controllerDataScope.userAlias(), controllerDataScope.isUser());
            }
        }
    }
@@ -102,65 +96,54 @@
     * @param user ç”¨æˆ·
     * @param userAlias åˆ«å
     */
    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
    {
    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, boolean isUser) {
        StringBuilder sqlString = new StringBuilder();
        for (SysRole role : user.getRoles())
        {
        // å°† "." æå–出,不写别名为单表查询,写别名为多表查询
        deptAlias = StrUtil.isNotBlank(deptAlias) ? deptAlias + "." : "";
        userAlias = StrUtil.isNotBlank(userAlias) ? userAlias + "." : "";
        for (SysRole role : user.getRoles()) {
            String dataScope = role.getDataScope();
            if (DATA_SCOPE_ALL.equals(dataScope))
            {
            if (DATA_SCOPE_ALL.equals(dataScope)) {
                sqlString = new StringBuilder();
                break;
            }
            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
            {
            } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
                sqlString.append(StrUtil.format(
                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
                        role.getRoleId()));
            }
            else if (DATA_SCOPE_DEPT.equals(dataScope))
            {
                sqlString.append(StrUtil.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
            }
            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
            {
                    " OR {}dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ",
                    deptAlias, role.getRoleId()));
            } else if (DATA_SCOPE_DEPT.equals(dataScope)) {
                sqlString.append(StrUtil.format(" OR {}dept_id = {} ",
                    deptAlias, user.getDeptId()));
            } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
                sqlString.append(StrUtil.format(
                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
                    " OR {}dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
                        deptAlias, user.getDeptId(), user.getDeptId()));
            }
            else if (DATA_SCOPE_SELF.equals(dataScope))
            {
                if (StrUtil.isNotBlank(userAlias))
                {
                    sqlString.append(StrUtil.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
                }
                else
                {
            } else if (DATA_SCOPE_SELF.equals(dataScope)) {
                if (isUser) {
                    sqlString.append(StrUtil.format(" OR {}user_id = {} ",
                        userAlias, user.getUserId()));
                } else {
                    // æ•°æ®æƒé™ä¸ºä»…本人且没有userAlias别名不查询任何数据
                    sqlString.append(" OR 1=0 ");
                }
            }
        }
        if (StrUtil.isNotBlank(sqlString.toString()))
        {
            putDataScope(joinPoint, "AND (" + sqlString.substring(4) + ")");
        if (StrUtil.isNotBlank(sqlString.toString())) {
            putDataScope(joinPoint, sqlString.substring(4));
        }
    }
    /**
     * æ˜¯å¦å­˜åœ¨æ³¨è§£ï¼Œå¦‚果存在就获取
     */
    private DataScope getAnnotationLog(JoinPoint joinPoint)
    {
    private DataScope getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null)
        {
        if (method != null) {
            return method.getAnnotation(DataScope.class);
        }
        return null;
@@ -169,22 +152,19 @@
    /**
     * æ‹¼æŽ¥æƒé™sql前先清空params.dataScope参数防止注入
     */
    private void clearDataScope(final JoinPoint joinPoint)
    {
    private void clearDataScope(final JoinPoint joinPoint) {
        Object params = joinPoint.getArgs()[0];
        if (Validator.isNotNull(params))
        {
        if (Validator.isNotNull(params)) {
            putDataScope(joinPoint, "");
        }
    }
    private static void putDataScope(JoinPoint joinPoint, String sql) {
        Object params = joinPoint.getArgs()[0];
        if (Validator.isNotNull(params))
        {
        if (Validator.isNotNull(params)) {
            if(params instanceof BaseEntity) {
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(DATA_SCOPE, "");
                baseEntity.getParams().put(DATA_SCOPE, sql);
            } else {
                try {
                    Method getParams = params.getClass().getDeclaredMethod("getParams", null);
ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
package com.ruoyi.framework.config;
import com.ruoyi.common.exception.CustomException;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@EnableAsync
@Configuration
public class AsyncConfig extends AsyncConfigurerSupport {
    /**
     * å¼‚步执行需要使用权限框架自带的包装线程池  ä¿è¯æƒé™ä¿¡æ¯çš„传递
     */
    @Override
    public Executor getAsyncExecutor() {
        return new DelegatingSecurityContextExecutorService(
            Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()));
    }
    /**
     * å¼‚步执行异常处理
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, objects) -> {
            throwable.printStackTrace();
            throw new CustomException(
                    "Exception message - " + throwable.getMessage()
                    + ", Method name - " + method.getName()
                    + ", Parameter value - " + Arrays.toString(objects));
        };
    }
}
ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
@@ -1,42 +1,69 @@
package com.ruoyi.framework.config;
import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import com.ruoyi.framework.config.properties.RedissonProperties;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.io.IOException;
/**
 * redis配置
 *
 * @author ruoyi
 * @author Lion Li
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{
    @Bean
    @SuppressWarnings(value = { "unchecked", "rawtypes" })
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
    {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
public class RedisConfig extends CachingConfigurerSupport {
        GenericFastJsonRedisSerializer serializer = new GenericFastJsonRedisSerializer();
        StringRedisSerializer keySerializer = new StringRedisSerializer();
    private static final String REDIS_PROTOCOL_PREFIX = "redis://";
    private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
        // ä½¿ç”¨StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(keySerializer);
        template.setValueSerializer(serializer);
    @Autowired
    private RedisProperties redisProperties;
        // Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(keySerializer);
        template.setHashValueSerializer(serializer);
    @Autowired
    private RedissonProperties redissonProperties;
        template.afterPropertiesSet();
        return template;
    @Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean(RedissonClient.class)
    public RedissonClient redisson() throws IOException {
        String prefix = REDIS_PROTOCOL_PREFIX;
        if (redisProperties.isSsl()) {
            prefix = REDISS_PROTOCOL_PREFIX;
        }
        Config config = new Config();
        config.setThreads(redissonProperties.getThreads())
            .setNettyThreads(redissonProperties.getNettyThreads())
            .setCodec(JsonJacksonCodec.INSTANCE)
            .setTransportMode(redissonProperties.getTransportMode());
        RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
        // ä½¿ç”¨å•机模式
        config.useSingleServer()
            .setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
            .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
            .setDatabase(redisProperties.getDatabase())
            .setPassword(redisProperties.getPassword())
            .setTimeout(singleServerConfig.getTimeout())
            .setRetryAttempts(singleServerConfig.getRetryAttempts())
            .setRetryInterval(singleServerConfig.getRetryInterval())
            .setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
            .setClientName(singleServerConfig.getClientName())
            .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
            .setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
            .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
            .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
            .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
            .setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
        return Redisson.create(config);
    }
}
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
package com.ruoyi.framework.config.properties;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.redisson.client.codec.Codec;
import org.redisson.config.TransportMode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * Redisson é…ç½®å±žæ€§
 *
 * @author Lion Li
 */
@Data
@Component
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {
    /**
     * çº¿ç¨‹æ± æ•°é‡,默认值 = å½“前处理核数量 * 2
     */
    private int threads;
    /**
     * Netty线程池数量,默认值 = å½“前处理核数量 * 2
     */
    private int nettyThreads;
    /**
     * ä¼ è¾“模式
     */
    private TransportMode transportMode;
    /**
     * å•机服务配置
     */
    private SingleServerConfig singleServerConfig;
    @Data
    @NoArgsConstructor
    public static class SingleServerConfig {
        /**
         * å®¢æˆ·ç«¯åç§°
         */
        private String clientName;
        /**
         * æœ€å°ç©ºé—²è¿žæŽ¥æ•°
         */
        private int connectionMinimumIdleSize;
        /**
         * è¿žæŽ¥æ± å¤§å°
         */
        private int connectionPoolSize;
        /**
         * è¿žæŽ¥ç©ºé—²è¶…时,单位:毫秒
         */
        private int idleConnectionTimeout;
        /**
         * å‘½ä»¤ç­‰å¾…超时,单位:毫秒
         */
        private int timeout;
        /**
         * å¦‚果尝试在此限制之内发送成功,则开始启用 timeout è®¡æ—¶ã€‚
         */
        private int retryAttempts;
        /**
         * å‘½ä»¤é‡è¯•发送时间间隔,单位:毫秒
         */
        private int retryInterval;
        /**
         * å‘布和订阅连接的最小空闲连接数
         */
        private int subscriptionConnectionMinimumIdleSize;
        /**
         * å‘布和订阅连接池大小
         */
        private int subscriptionConnectionPoolSize;
        /**
         * å•个连接最大订阅数量
         */
        private int subscriptionsPerConnection;
        /**
         * DNS监测时间间隔,单位:毫秒
         */
        private int dnsMonitoringInterval;
    }
}
ruoyi-generator/src/main/resources/vm/java/addBo.java.vm
@@ -24,6 +24,7 @@
#foreach ($column in $columns)
#if($column.isInsert && $column.isPk!=1)
    /** $column.columnComment */
    @ApiModelProperty("$column.columnComment")
#if($column.javaType == 'Date')
ruoyi-generator/src/main/resources/vm/java/domain.java.vm
@@ -34,6 +34,9 @@
#end
#if($column.javaField=='delFlag')
    @TableLogic
#end
#if($column.javaField=='version')
    @Version
#end
#if($column.isPk==1)
    @TableId(value = "$column.columnName")
ruoyi-generator/src/main/resources/vm/java/service.java.vm
@@ -32,6 +32,7 @@
     */
    TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}QueryBo bo);
#end
    /**
     * æŸ¥è¯¢åˆ—表
     */
ruoyi-generator/src/main/resources/vm/java/vo.java.vm
@@ -13,7 +13,7 @@
/**
 * ${functionName}视图对象 mall_package
 * ${functionName}视图对象 ${tableName}
 *
 * @author ${author}
 * @date ${datetime}
@@ -21,6 +21,7 @@
@Data
@ApiModel("${functionName}视图对象")
public class ${ClassName}Vo {
    private static final long serialVersionUID = 1L;
    /** $pkColumn.columnComment */
@@ -46,6 +47,7 @@
#end
    @ApiModelProperty("$column.columnComment")
    private $column.javaType $column.javaField;
#end
#end
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
@@ -30,4 +30,12 @@
     */
    public List<Integer> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
    /**
     * ä¿®æ”¹å­å…ƒç´ å…³ç³»
     *
     * @param depts å­å…ƒç´ 
     * @return ç»“æžœ
     */
    public int updateDeptChildren(@Param("depts") List<SysDept> depts);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
@@ -3,6 +3,8 @@
import com.ruoyi.common.core.page.BaseMapperPlus;
import com.ruoyi.system.domain.SysRoleDept;
import java.util.List;
/**
 * è§’色与部门关联表 æ•°æ®å±‚
 *
@@ -10,4 +12,12 @@
 */
public interface SysRoleDeptMapper extends BaseMapperPlus<SysRoleDept> {
    /**
     * æ‰¹é‡æ–°å¢žè§’色部门信息
     *
     * @param roleDeptList è§’色部门列表
     * @return ç»“æžœ
     */
    public int batchRoleDept(List<SysRoleDept> roleDeptList);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
@@ -3,6 +3,8 @@
import com.ruoyi.common.core.page.BaseMapperPlus;
import com.ruoyi.system.domain.SysRoleMenu;
import java.util.List;
/**
 * è§’色与菜单关联表 æ•°æ®å±‚
 *
@@ -10,4 +12,12 @@
 */
public interface SysRoleMenuMapper extends BaseMapperPlus<SysRoleMenu> {
    /**
     * æ‰¹é‡æ–°å¢žè§’色菜单信息
     *
     * @param roleMenuList è§’色菜单列表
     * @return ç»“æžœ
     */
    public int batchRoleMenu(List<SysRoleMenu> roleMenuList);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
@@ -3,6 +3,8 @@
import com.ruoyi.common.core.page.BaseMapperPlus;
import com.ruoyi.system.domain.SysUserPost;
import java.util.List;
/**
 * ç”¨æˆ·ä¸Žå²—位关联表 æ•°æ®å±‚
 *
@@ -10,4 +12,12 @@
 */
public interface SysUserPostMapper extends BaseMapperPlus<SysUserPost> {
    /**
     * æ‰¹é‡æ–°å¢žç”¨æˆ·å²—位信息
     *
     * @param userPostList ç”¨æˆ·è§’色列表
     * @return ç»“æžœ
     */
    public int batchUserPost(List<SysUserPost> userPostList);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
@@ -3,6 +3,8 @@
import com.ruoyi.common.core.page.BaseMapperPlus;
import com.ruoyi.system.domain.SysUserRole;
import java.util.List;
/**
 * ç”¨æˆ·ä¸Žè§’色关联表 æ•°æ®å±‚
 *
@@ -10,4 +12,12 @@
 */
public interface SysUserRoleMapper extends BaseMapperPlus<SysUserRole> {
    /**
     * æ‰¹é‡æ–°å¢žç”¨æˆ·è§’色信息
     *
     * @param userRoleList ç”¨æˆ·è§’色列表
     * @return ç»“æžœ
     */
    public int batchUserRole(List<SysUserRole> userRoleList);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
@@ -20,6 +20,7 @@
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -31,9 +32,6 @@
 */
@Service
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements ISysConfigService {
    @Autowired
    private SysConfigMapper configMapper;
    @Autowired
    private RedisCache redisCache;
@@ -160,9 +158,9 @@
            if (StrUtil.equals(UserConstants.YES, config.getConfigType())) {
                throw new CustomException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
            }
            configMapper.deleteById(configId);
            redisCache.deleteObject(getCacheKey(config.getConfigKey()));
        }
        baseMapper.deleteBatchIds(Arrays.asList(configIds));
    }
    /**
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
@@ -244,7 +244,7 @@
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            updateBatchById(children);
            baseMapper.updateDeptChildren(children);
        }
    }
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
@@ -11,6 +11,7 @@
import com.ruoyi.system.service.ISysDictDataService;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
/**
@@ -83,10 +84,10 @@
    public void deleteDictDataByIds(Long[] dictCodes) {
        for (Long dictCode : dictCodes) {
            SysDictData data = selectDictDataById(dictCode);
            baseMapper.deleteById(dictCode);
            List<SysDictData> dictDatas = baseMapper.selectDictDataByType(data.getDictType());
            DictUtils.setDictCache(data.getDictType(), dictDatas);
        }
        baseMapper.deleteBatchIds(Arrays.asList(dictCodes));
    }
    /**
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
@@ -21,6 +21,7 @@
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -31,9 +32,6 @@
 */
@Service
public class SysDictTypeServiceImpl extends ServiceImpl<SysDictTypeMapper, SysDictType> implements ISysDictTypeService {
    @Autowired
    private SysDictTypeMapper dictTypeMapper;
    @Autowired
    private SysDictDataMapper dictDataMapper;
@@ -149,9 +147,9 @@
                .eq(SysDictData::getDictType, dictType.getDictType())) > 0) {
                throw new CustomException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
            }
            dictTypeMapper.deleteById(dictId);
            DictUtils.removeDictCache(dictType.getDictType());
        }
        baseMapper.deleteBatchIds(Arrays.asList(dictIds));
    }
    /**
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
@@ -240,9 +240,7 @@
            list.add(rm);
        }
        if (list.size() > 0) {
            for (SysRoleMenu sysRoleMenu : list) {
                rows += roleMenuMapper.insert(sysRoleMenu);
            }
            rows = roleMenuMapper.batchRoleMenu(list);
        }
        return rows;
    }
@@ -263,9 +261,7 @@
            list.add(rd);
        }
        if (list.size() > 0) {
            for (SysRoleDept sysRoleDept : list) {
                rows += roleDeptMapper.insert(sysRoleDept);
            }
            rows = roleDeptMapper.batchRoleDept(list);
        }
        return rows;
    }
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -52,7 +52,7 @@
    private ISysConfigService configService;
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    @DataScope(deptAlias = "d", userAlias = "u", isUser = true)
    public TableDataInfo<SysUser> selectPageUserList(SysUser user) {
        return PageUtils.buildDataInfo(baseMapper.selectPageUserList(PageUtils.buildPage(), user));
    }
@@ -64,7 +64,7 @@
     * @return ç”¨æˆ·ä¿¡æ¯é›†åˆä¿¡æ¯
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    @DataScope(deptAlias = "d", userAlias = "u", isUser = true)
    public List<SysUser> selectUserList(SysUser user) {
        return baseMapper.selectUserList(user);
    }
@@ -100,7 +100,7 @@
    @Override
    public String selectUserRoleGroup(String userName) {
        List<SysRole> list = roleMapper.selectRolesByUserName(userName);
        StringBuffer idsStr = new StringBuffer();
        StringBuilder idsStr = new StringBuilder();
        for (SysRole role : list) {
            idsStr.append(role.getRoleName()).append(",");
        }
@@ -119,7 +119,7 @@
    @Override
    public String selectUserPostGroup(String userName) {
        List<SysPost> list = postMapper.selectPostsByUserName(userName);
        StringBuffer idsStr = new StringBuffer();
        StringBuilder idsStr = new StringBuilder();
        for (SysPost post : list) {
            idsStr.append(post.getPostName()).append(",");
        }
@@ -311,9 +311,7 @@
                list.add(ur);
            }
            if (list.size() > 0) {
                for (SysUserRole sysUserRole : list) {
                    userRoleMapper.insert(sysUserRole);
                }
                userRoleMapper.batchUserRole(list);
            }
        }
    }
@@ -335,9 +333,7 @@
                list.add(up);
            }
            if (list.size() > 0) {
                for (SysUserPost sysUserPost : list) {
                    userPostMapper.insert(sysUserPost);
                }
                userPostMapper.batchUserPost(list);
            }
        }
    }
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -40,7 +40,9 @@
            AND status = #{status}
        </if>
        <!-- æ•°æ®èŒƒå›´è¿‡æ»¤ -->
        ${params.dataScope}
        <if test="params.dataScope != null and params.dataScope != ''">
            AND ( ${params.dataScope} )
        </if>
        order by d.parent_id, d.order_num
    </select>
@@ -55,4 +57,17 @@
        order by d.parent_id, d.order_num
    </select>
    <update id="updateDeptChildren" parameterType="java.util.List">
        update sys_dept set ancestors =
        <foreach collection="depts" item="item" index="index"
                 separator=" " open="case dept_id" close="end">
            when #{item.deptId} then #{item.ancestors}
        </foreach>
        where dept_id in
        <foreach collection="depts" item="item" index="index"
                 separator="," open="(" close=")">
            #{item.deptId}
        </foreach>
    </update>
</mapper>
ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
@@ -9,4 +9,11 @@
        <result property="deptId" column="dept_id"/>
    </resultMap>
    <insert id="batchRoleDept">
        insert into sys_role_dept(role_id, dept_id) values
        <foreach item="item" index="index" collection="list" separator=",">
            (#{item.roleId},#{item.deptId})
        </foreach>
    </insert>
</mapper> 
ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
@@ -58,7 +58,9 @@
            and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{role.params.endTime},'%y%m%d')
        </if>
        <!-- æ•°æ®èŒƒå›´è¿‡æ»¤ -->
        ${role.params.dataScope}
        <if test="role.params.dataScope != null and role.params.dataScope != ''">
            AND ( ${role.params.dataScope} )
        </if>
        order by r.role_sort
    </select>
@@ -81,7 +83,9 @@
            and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
        </if>
        <!-- æ•°æ®èŒƒå›´è¿‡æ»¤ -->
        ${params.dataScope}
        <if test="params.dataScope != null and params.dataScope != ''">
            AND ( ${params.dataScope} )
        </if>
        order by r.role_sort
    </select>
ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
@@ -9,4 +9,11 @@
        <result property="menuId" column="menu_id"/>
    </resultMap>
    <insert id="batchRoleMenu">
        insert into sys_role_menu(role_id, menu_id) values
        <foreach item="item" index="index" collection="list" separator=",">
            (#{item.roleId},#{item.menuId})
        </foreach>
    </insert>
</mapper> 
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -106,7 +106,9 @@
            ancestors) ))
        </if>
        <!-- æ•°æ®èŒƒå›´è¿‡æ»¤ -->
        ${user.params.dataScope}
        <if test="user.params.dataScope != null and user.params.dataScope != ''">
            AND ( ${user.params.dataScope} )
        </if>
    </select>
    <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
@@ -135,7 +137,9 @@
            ancestors) ))
        </if>
        <!-- æ•°æ®èŒƒå›´è¿‡æ»¤ -->
        ${params.dataScope}
        <if test="params.dataScope != null and params.dataScope != ''">
            AND ( ${params.dataScope} )
        </if>
    </select>
    <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml
@@ -9,4 +9,11 @@
        <result property="postId" column="post_id"/>
    </resultMap>
    <insert id="batchUserPost">
        insert into sys_user_post(user_id, post_id) values
        <foreach item="item" index="index" collection="list" separator=",">
            (#{item.userId},#{item.postId})
        </foreach>
    </insert>
</mapper> 
ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
@@ -9,4 +9,11 @@
        <result property="roleId" column="role_id"/>
    </resultMap>
    <insert id="batchUserRole">
        insert into sys_user_role(user_id, role_id) values
        <foreach item="item" index="index" collection="list" separator=",">
            (#{item.userId},#{item.roleId})
        </foreach>
    </insert>
</mapper> 
ruoyi-ui/package.json
@@ -1,6 +1,6 @@
{
  "name": "ruoyi-vue-plus",
  "version": "2.2.1",
  "version": "2.3.0",
  "description": "RuoYi-Vue-Plus后台管理系统",
  "author": "LionLi",
  "license": "MIT",
ruoyi-ui/src/api/demo/demo.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
import request from '@/utils/request'
// æŸ¥è¯¢æµ‹è¯•单表列表
export function listDemo(query) {
  return request({
    url: '/demo/demo/list',
    method: 'get',
    params: query
  })
}
// æŸ¥è¯¢æµ‹è¯•单表详细
export function getDemo(id) {
  return request({
    url: '/demo/demo/' + id,
    method: 'get'
  })
}
// æ–°å¢žæµ‹è¯•单表
export function addDemo(data) {
  return request({
    url: '/demo/demo',
    method: 'post',
    data: data
  })
}
// ä¿®æ”¹æµ‹è¯•单表
export function updateDemo(data) {
  return request({
    url: '/demo/demo',
    method: 'put',
    data: data
  })
}
// åˆ é™¤æµ‹è¯•单表
export function delDemo(id) {
  return request({
    url: '/demo/demo/' + id,
    method: 'delete'
  })
}
// å¯¼å‡ºæµ‹è¯•单表
export function exportDemo(query) {
  return request({
    url: '/demo/demo/export',
    method: 'get',
    params: query
  })
}
ruoyi-ui/src/api/demo/test.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
import request from '@/utils/request'
// æŸ¥è¯¢æµ‹è¯•列表
export function listTest(query) {
  return request({
    url: '/demo/test/list',
    method: 'get',
    params: query
  })
}
// æŸ¥è¯¢æµ‹è¯•详细
export function getTest(id) {
  return request({
    url: '/demo/test/' + id,
    method: 'get'
  })
}
// æ–°å¢žæµ‹è¯•
export function addTest(data) {
  return request({
    url: '/demo/test',
    method: 'post',
    data: data
  })
}
// ä¿®æ”¹æµ‹è¯•
export function updateTest(data) {
  return request({
    url: '/demo/test',
    method: 'put',
    data: data
  })
}
// åˆ é™¤æµ‹è¯•
export function delTest(id) {
  return request({
    url: '/demo/test/' + id,
    method: 'delete'
  })
}
// å¯¼å‡ºæµ‹è¯•
export function exportTest(query) {
  return request({
    url: '/demo/test/export',
    method: 'get',
    params: query
  })
}
ruoyi-ui/src/api/demo/tree.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
import request from '@/utils/request'
// æŸ¥è¯¢æµ‹è¯•树表列表
export function listTree(query) {
  return request({
    url: '/demo/tree/list',
    method: 'get',
    params: query
  })
}
// æŸ¥è¯¢æµ‹è¯•树表详细
export function getTree(id) {
  return request({
    url: '/demo/tree/' + id,
    method: 'get'
  })
}
// æ–°å¢žæµ‹è¯•树表
export function addTree(data) {
  return request({
    url: '/demo/tree',
    method: 'post',
    data: data
  })
}
// ä¿®æ”¹æµ‹è¯•树表
export function updateTree(data) {
  return request({
    url: '/demo/tree',
    method: 'put',
    data: data
  })
}
// åˆ é™¤æµ‹è¯•树表
export function delTree(id) {
  return request({
    url: '/demo/tree/' + id,
    method: 'delete'
  })
}
// å¯¼å‡ºæµ‹è¯•树表
export function exportTree(query) {
  return request({
    url: '/demo/tree/export',
    method: 'get',
    params: query
  })
}
ruoyi-ui/src/views/demo/demo/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,339 @@
<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="key键" prop="testKey">
        <el-input
          v-model="queryParams.testKey"
          placeholder="请输入key键"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="值" prop="value">
        <el-input
          v-model="queryParams.value"
          placeholder="请输入值"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="创建时间">
        <el-date-picker
          v-model="daterangeCreateTime"
          size="small"
          style="width: 240px"
          value-format="yyyy-MM-dd"
          type="daterange"
          range-separator="-"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
        ></el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['demo:demo:add']"
        >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="el-icon-edit"
          size="mini"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['demo:demo:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="el-icon-delete"
          size="mini"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['demo:demo:remove']"
        >删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="el-icon-download"
          size="mini"
          :loading="exportLoading"
          @click="handleExport"
          v-hasPermi="['demo:demo:export']"
        >导出</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>
    <el-table v-loading="loading" :data="demoList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="主键" align="center" prop="id" v-if="false"/>
      <el-table-column label="部门id" align="center" prop="deptId" />
      <el-table-column label="用户id" align="center" prop="userId" />
      <el-table-column label="排序号" align="center" prop="orderNum" />
      <el-table-column label="key键" align="center" prop="testKey" />
      <el-table-column label="值" align="center" prop="value" />
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="创建人" align="center" prop="createBy" />
      <el-table-column label="更新时间" align="center" prop="updateTime" width="180">
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="更新人" align="center" prop="updateBy" />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['demo:demo:edit']"
          >修改</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['demo:demo:remove']"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•å•è¡¨å¯¹è¯æ¡† -->
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="部门id" prop="deptId">
          <el-input v-model="form.deptId" placeholder="请输入部门id" />
        </el-form-item>
        <el-form-item label="用户id" prop="userId">
          <el-input v-model="form.userId" placeholder="请输入用户id" />
        </el-form-item>
        <el-form-item label="排序号" prop="orderNum">
          <el-input v-model="form.orderNum" placeholder="请输入排序号" />
        </el-form-item>
        <el-form-item label="key键" prop="testKey">
          <el-input v-model="form.testKey" placeholder="请输入key键" />
        </el-form-item>
        <el-form-item label="值" prop="value">
          <el-input v-model="form.value" placeholder="请输入值" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
        <el-button @click="cancel">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { listDemo, getDemo, delDemo, addDemo, updateDemo, exportDemo } from "@/api/demo/demo";
export default {
  name: "Demo",
  components: {
  },
  data() {
    return {
      // é®ç½©å±‚
      loading: true,
      // å¯¼å‡ºé®ç½©å±‚
      exportLoading: false,
      // é€‰ä¸­æ•°ç»„
      ids: [],
      // éžå•个禁用
      single: true,
      // éžå¤šä¸ªç¦ç”¨
      multiple: true,
      // æ˜¾ç¤ºæœç´¢æ¡ä»¶
      showSearch: true,
      // æ€»æ¡æ•°
      total: 0,
      // æµ‹è¯•单表表格数据
      demoList: [],
      // å¼¹å‡ºå±‚标题
      title: "",
      // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚
      open: false,
      // åˆ›å»ºæ—¶é—´æ—¶é—´èŒƒå›´
      daterangeCreateTime: [],
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        testKey: undefined,
        value: undefined,
        createTime: undefined,
      },
      // è¡¨å•参数
      form: {},
      // è¡¨å•校验
      rules: {
        testKey: [
          { required: true, message: "key键不能为空", trigger: "blur" }
        ],
        value: [
          { required: true, message: "值不能为空", trigger: "blur" }
        ],
      }
    };
  },
  created() {
    this.getList();
  },
  methods: {
    /** æŸ¥è¯¢æµ‹è¯•单表列表 */
    getList() {
      this.loading = true;
      this.queryParams.params = {};
      if (null != this.daterangeCreateTime && '' != this.daterangeCreateTime) {
        this.queryParams.params["beginCreateTime"] = this.daterangeCreateTime[0];
        this.queryParams.params["endCreateTime"] = this.daterangeCreateTime[1];
      }
      listDemo(this.queryParams).then(response => {
        this.demoList = response.rows;
        this.total = response.total;
        this.loading = false;
      });
    },
    // å–消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // è¡¨å•重置
    reset() {
      this.form = {
        id: undefined,
        deptId: undefined,
        userId: undefined,
        orderNum: undefined,
        testKey: undefined,
        value: undefined,
        version: undefined,
        createTime: undefined,
        createBy: undefined,
        updateTime: undefined,
        updateBy: undefined,
        delFlag: undefined
      };
      this.resetForm("form");
    },
    /** æœç´¢æŒ‰é’®æ“ä½œ */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** é‡ç½®æŒ‰é’®æ“ä½œ */
    resetQuery() {
      this.daterangeCreateTime = [];
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id)
      this.single = selection.length!==1
      this.multiple = !selection.length
    },
    /** æ–°å¢žæŒ‰é’®æ“ä½œ */
    handleAdd() {
      this.reset();
      this.open = true;
      this.title = "添加测试单表";
    },
    /** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
    handleUpdate(row) {
      this.reset();
      const id = row.id || this.ids
      getDemo(id).then(response => {
        this.form = response.data;
        this.open = true;
        this.title = "修改测试单表";
      });
    },
    /** æäº¤æŒ‰é’® */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          if (this.form.id != null) {
            updateDemo(this.form).then(response => {
              this.msgSuccess("修改成功");
              this.open = false;
              this.getList();
            });
          } else {
            addDemo(this.form).then(response => {
              this.msgSuccess("新增成功");
              this.open = false;
              this.getList();
            });
          }
        }
      });
    },
    /** åˆ é™¤æŒ‰é’®æ“ä½œ */
    handleDelete(row) {
      const ids = row.id || this.ids;
      this.$confirm('是否确认删除测试单表编号为"' + ids + '"的数据项?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(function() {
        return delDemo(ids);
      }).then(() => {
        this.getList();
        this.msgSuccess("删除成功");
      })
    },
    /** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
    handleExport() {
      const queryParams = this.queryParams;
      this.$confirm('是否确认导出所有测试单表数据项?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        this.exportLoading = true;
        return exportDemo(queryParams);
      }).then(response => {
        this.download(response.msg);
        this.exportLoading = false;
      })
    }
  }
};
</script>
ruoyi-ui/src/views/demo/test/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,361 @@
<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="key键" prop="testKey">
        <el-input
          v-model="queryParams.testKey"
          placeholder="请输入key键"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="值" prop="value">
        <el-input
          v-model="queryParams.value"
          placeholder="请输入值"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="版本" prop="version">
        <el-input
          v-model="queryParams.version"
          placeholder="请输入版本"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="创建时间">
        <el-date-picker
          v-model="daterangeCreateTime"
          size="small"
          style="width: 240px"
          value-format="yyyy-MM-dd"
          type="daterange"
          range-separator="-"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
        ></el-date-picker>
      </el-form-item>
      <el-form-item label="删除标志" prop="deleted">
        <el-input
          v-model="queryParams.deleted"
          placeholder="请输入删除标志"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="父id" prop="parentId">
        <el-input
          v-model="queryParams.parentId"
          placeholder="请输入父id"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="排序号" prop="orderNum">
        <el-input
          v-model="queryParams.orderNum"
          placeholder="请输入排序号"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['demo:test:add']"
        >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="el-icon-edit"
          size="mini"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['demo:test:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="el-icon-delete"
          size="mini"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['demo:test:remove']"
        >删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="el-icon-download"
          size="mini"
          @click="handleExport"
          v-hasPermi="['demo:test:export']"
        >导出</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>
    <el-table v-loading="loading" :data="testList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="主键" align="center" prop="id" v-if="false"/>
      <el-table-column label="key键" align="center" prop="testKey" />
      <el-table-column label="值" align="center" prop="value" />
      <el-table-column label="版本" align="center" prop="version" />
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="删除标志" align="center" prop="deleted" />
      <el-table-column label="父id" align="center" prop="parentId" />
      <el-table-column label="排序号" align="center" prop="orderNum" />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['demo:test:edit']"
          >修改</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['demo:test:remove']"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•å¯¹è¯æ¡† -->
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="key键" prop="testKey">
          <el-input v-model="form.testKey" placeholder="请输入key键" />
        </el-form-item>
        <el-form-item label="值" prop="value">
          <el-input v-model="form.value" placeholder="请输入值" />
        </el-form-item>
        <el-form-item label="版本" prop="version">
          <el-input v-model="form.version" placeholder="请输入版本" />
        </el-form-item>
        <el-form-item label="删除标志" prop="deleted">
          <el-input v-model="form.deleted" placeholder="请输入删除标志" />
        </el-form-item>
        <el-form-item label="父id" prop="parentId">
          <el-input v-model="form.parentId" placeholder="请输入父id" />
        </el-form-item>
        <el-form-item label="排序号" prop="orderNum">
          <el-input v-model="form.orderNum" placeholder="请输入排序号" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
        <el-button @click="cancel">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { listTest, getTest, delTest, addTest, updateTest, exportTest } from "@/api/demo/test";
export default {
  name: "Test",
  components: {
  },
  data() {
    return {
      // é®ç½©å±‚
      loading: true,
      // é€‰ä¸­æ•°ç»„
      ids: [],
      // éžå•个禁用
      single: true,
      // éžå¤šä¸ªç¦ç”¨
      multiple: true,
      // æ˜¾ç¤ºæœç´¢æ¡ä»¶
      showSearch: true,
      // æ€»æ¡æ•°
      total: 0,
      // æµ‹è¯•表格数据
      testList: [],
      // å¼¹å‡ºå±‚标题
      title: "",
      // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚
      open: false,
      // åˆ›å»ºæ—¶é—´æ—¶é—´èŒƒå›´
      daterangeCreateTime: [],
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        testKey: undefined,
        value: undefined,
        version: undefined,
        createTime: undefined,
        deleted: undefined,
        parentId: undefined,
        orderNum: undefined
      },
      // è¡¨å•参数
      form: {},
      // è¡¨å•校验
      rules: {
      }
    };
  },
  created() {
    this.getList();
  },
  methods: {
    /** æŸ¥è¯¢æµ‹è¯•列表 */
    getList() {
      this.loading = true;
      this.queryParams.params = {};
      if (null != this.daterangeCreateTime && '' != this.daterangeCreateTime) {
        this.queryParams.params["beginCreateTime"] = this.daterangeCreateTime[0];
        this.queryParams.params["endCreateTime"] = this.daterangeCreateTime[1];
      }
      listTest(this.queryParams).then(response => {
        this.testList = response.rows;
        this.total = response.total;
        this.loading = false;
      });
    },
    // å–消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // è¡¨å•重置
    reset() {
      this.form = {
        id: undefined,
        testKey: undefined,
        value: undefined,
        version: undefined,
        createTime: undefined,
        deleted: undefined,
        parentId: undefined,
        orderNum: undefined
      };
      this.resetForm("form");
    },
    /** æœç´¢æŒ‰é’®æ“ä½œ */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** é‡ç½®æŒ‰é’®æ“ä½œ */
    resetQuery() {
      this.daterangeCreateTime = [];
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id)
      this.single = selection.length!==1
      this.multiple = !selection.length
    },
    /** æ–°å¢žæŒ‰é’®æ“ä½œ */
    handleAdd() {
      this.reset();
      this.open = true;
      this.title = "添加测试";
    },
    /** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
    handleUpdate(row) {
      this.reset();
      const id = row.id || this.ids
      getTest(id).then(response => {
        this.form = response.data;
        this.open = true;
        this.title = "修改测试";
      });
    },
    /** æäº¤æŒ‰é’® */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          if (this.form.id != null) {
            updateTest(this.form).then(response => {
              this.msgSuccess("修改成功");
              this.open = false;
              this.getList();
            });
          } else {
            addTest(this.form).then(response => {
              this.msgSuccess("新增成功");
              this.open = false;
              this.getList();
            });
          }
        }
      });
    },
    /** åˆ é™¤æŒ‰é’®æ“ä½œ */
    handleDelete(row) {
      const ids = row.id || this.ids;
      this.$confirm('是否确认删除测试编号为"' + ids + '"的数据项?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(function() {
          return delTest(ids);
        }).then(() => {
          this.getList();
          this.msgSuccess("删除成功");
        })
    },
    /** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
    handleExport() {
      const queryParams = this.queryParams;
      this.$confirm('是否确认导出所有测试数据项?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(function() {
          return exportTest(queryParams);
        }).then(response => {
          this.download(response.msg);
        })
    }
  }
};
</script>
ruoyi-ui/src/views/demo/tree/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,282 @@
<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="树节点名" prop="treeName">
        <el-input
          v-model="queryParams.treeName"
          placeholder="请输入树节点名"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="创建时间">
        <el-date-picker
          v-model="daterangeCreateTime"
          size="small"
          style="width: 240px"
          value-format="yyyy-MM-dd"
          type="daterange"
          range-separator="-"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
        ></el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['demo:tree:add']"
        >新增</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>
    <el-table
      v-loading="loading"
      :data="treeList"
      row-key="id"
      default-expand-all
      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
    >
      <el-table-column label="父id" prop="parentId" />
      <el-table-column label="部门id" align="center" prop="deptId" />
      <el-table-column label="用户id" align="center" prop="userId" />
      <el-table-column label="树节点名" align="center" prop="treeName" />
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['demo:tree:edit']"
          >修改</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-plus"
            @click="handleAdd(scope.row)"
            v-hasPermi="['demo:tree:add']"
          >新增</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['demo:tree:remove']"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•æ ‘è¡¨å¯¹è¯æ¡† -->
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="父id" prop="parentId">
          <treeselect v-model="form.parentId" :options="treeOptions" :normalizer="normalizer" placeholder="请选择父id" />
        </el-form-item>
        <el-form-item label="部门id" prop="deptId">
          <el-input v-model="form.deptId" placeholder="请输入部门id" />
        </el-form-item>
        <el-form-item label="用户id" prop="userId">
          <el-input v-model="form.userId" placeholder="请输入用户id" />
        </el-form-item>
        <el-form-item label="树节点名" prop="treeName">
          <el-input v-model="form.treeName" placeholder="请输入树节点名" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
        <el-button @click="cancel">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { listTree, getTree, delTree, addTree, updateTree, exportTree } from "@/api/demo/tree";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
  name: "Tree",
  components: {
    Treeselect
  },
  data() {
    return {
      // é®ç½©å±‚
      loading: true,
      // æ˜¾ç¤ºæœç´¢æ¡ä»¶
      showSearch: true,
      // æµ‹è¯•树表表格数据
      treeList: [],
      // æµ‹è¯•树表树选项
      treeOptions: [],
      // å¼¹å‡ºå±‚标题
      title: "",
      // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚
      open: false,
      // åˆ›å»ºæ—¶é—´æ—¶é—´èŒƒå›´
      daterangeCreateTime: [],
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        treeName: null,
        createTime: null,
      },
      // è¡¨å•参数
      form: {},
      // è¡¨å•校验
      rules: {
        treeName: [
          { required: true, message: "树节点名不能为空", trigger: "blur" }
        ],
      }
    };
  },
  created() {
    this.getList();
  },
  methods: {
    /** æŸ¥è¯¢æµ‹è¯•树表列表 */
    getList() {
      this.loading = true;
      this.queryParams.params = {};
      if (null != this.daterangeCreateTime && '' != this.daterangeCreateTime) {
        this.queryParams.params["beginCreateTime"] = this.daterangeCreateTime[0];
        this.queryParams.params["endCreateTime"] = this.daterangeCreateTime[1];
      }
      listTree(this.queryParams).then(response => {
        this.treeList = this.handleTree(response.data, "id", "parentId");
        this.loading = false;
      });
    },
    /** è½¬æ¢æµ‹è¯•树表数据结构 */
    normalizer(node) {
      if (node.children && !node.children.length) {
        delete node.children;
      }
      return {
        id: node.id,
        label: node.treeName,
        children: node.children
      };
    },
    /** æŸ¥è¯¢æµ‹è¯•树表下拉树结构 */
    getTreeselect() {
      listTree().then(response => {
        this.treeOptions = [];
        const data = { id: 0, treeName: '顶级节点', children: [] };
        data.children = this.handleTree(response.data, "id", "parentId");
        this.treeOptions.push(data);
      });
    },
    // å–消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // è¡¨å•重置
    reset() {
      this.form = {
        id: null,
        parentId: null,
        deptId: null,
        userId: null,
        treeName: null,
        version: null,
        createTime: null,
        createBy: null,
        updateTime: null,
        updateBy: null,
        delFlag: null
      };
      this.resetForm("form");
    },
    /** æœç´¢æŒ‰é’®æ“ä½œ */
    handleQuery() {
      this.getList();
    },
    /** é‡ç½®æŒ‰é’®æ“ä½œ */
    resetQuery() {
      this.daterangeCreateTime = [];
      this.resetForm("queryForm");
      this.handleQuery();
    },
    /** æ–°å¢žæŒ‰é’®æ“ä½œ */
    handleAdd(row) {
      this.reset();
      this.getTreeselect();
      if (row != null && row.id) {
        this.form.parentId = row.id;
      } else {
        this.form.parentId = 0;
      }
      this.open = true;
      this.title = "添加测试树表";
    },
    /** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
    handleUpdate(row) {
      this.reset();
      this.getTreeselect();
      if (row != null) {
        this.form.parentId = row.id;
      }
      getTree(row.id).then(response => {
        this.form = response.data;
        this.open = true;
        this.title = "修改测试树表";
      });
    },
    /** æäº¤æŒ‰é’® */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          if (this.form.id != null) {
            updateTree(this.form).then(response => {
              this.msgSuccess("修改成功");
              this.open = false;
              this.getList();
            });
          } else {
            addTree(this.form).then(response => {
              this.msgSuccess("新增成功");
              this.open = false;
              this.getList();
            });
          }
        }
      });
    },
    /** åˆ é™¤æŒ‰é’®æ“ä½œ */
    handleDelete(row) {
      this.$confirm('是否确认删除测试树表编号为"' + row.id + '"的数据项?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(function() {
        return delTree(row.id);
      }).then(() => {
        this.getList();
        this.msgSuccess("删除成功");
      })
    }
  }
};
</script>
ruoyi-ui/src/views/index.vue
@@ -80,6 +80,16 @@
            <span>更新日志</span>
          </div>
          <el-collapse accordion>
            <el-collapse-item title="v2.3.0 - 2021-6-1">
              <ol>
                <li>add å‡çº§ luttuce ä¸º redisson æ€§èƒ½æ›´å¼º å·¥å…·æ›´å…¨</li>
                <li>add å¢žåŠ æµ‹è¯•æ•°æ®sql文件</li>
                <li>add å¢žåŠ demo模块 å•表演示案例(包含数据权限)</li>
                <li>update å®Œç¾Žä¿®å¤ æ•°æ®æƒé™åŠŸèƒ½(支持单表多表过滤)</li>
                <li>update ä¼˜åŒ–代码生成模板</li>
                <li>update ä¼˜åŒ– system æ¨¡å— æ‰¹é‡æ“ä½œæ€§èƒ½</li>
              </ol>
            </el-collapse-item>
            <el-collapse-item title="v2.2.1 - 2021-5-29">
              <ol>
                <li>add å¢žåŠ  security æƒé™æ¡†æž¶ @Async å¼‚步注解配置</li>
ry.bat
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
@echo off
rem jar平级目录
set AppName=ruoyi-admin.jar
rem JVM参数
set JVM_OPTS="-Dname=%AppName%  -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps  -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
ECHO.
    ECHO.  [1] å¯åЍ%AppName%
    ECHO.  [2] å…³é—­%AppName%
    ECHO.  [3] é‡å¯%AppName%
    ECHO.  [4] å¯åŠ¨çŠ¶æ€ %AppName%
    ECHO.  [5] é€€ å‡º
ECHO.
ECHO.请输入选择项目的序号:
set /p ID=
    IF "%id%"=="1" GOTO start
    IF "%id%"=="2" GOTO stop
    IF "%id%"=="3" GOTO restart
    IF "%id%"=="4" GOTO status
    IF "%id%"=="5" EXIT
PAUSE
:start
    for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
        set pid=%%a
        set image_name=%%b
    )
    if  defined pid (
        echo %%is running
        PAUSE
    )
start javaw -jar %JAVA_OPTS% ruoyi-admin.jar
echo  starting……
echo  Start %AppName% success...
goto:eof
rem å‡½æ•°stop通过jps命令查找pid并结束进程
:stop
    for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
        set pid=%%a
        set image_name=%%b
    )
    if not defined pid (echo process %AppName% does not exists) else (
        echo prepare to kill %image_name%
        echo start kill %pid% ...
        rem æ ¹æ®è¿›ç¨‹ID,kill进程
        taskkill /f /pid %pid%
    )
goto:eof
:restart
    call :stop
    call :start
goto:eof
:status
    for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
        set pid=%%a
        set image_name=%%b
    )
    if not defined pid (echo process %AppName% is dead ) else (
        echo %image_name% is running
    )
goto:eof
ry.sh
@@ -1,5 +1,9 @@
#!/bin/bash
#!/bin/sh
# author ruoyi
# ./ry.sh start å¯åЍ
# ./ry.sh stop åœæ­¢
# ./ry.sh restart é‡å¯
# ./ry.sh start çŠ¶æ€
AppName=ruoyi-admin.jar
#JVM参数
sql/test.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,171 @@
DROP TABLE if EXISTS test_demo;
CREATE TABLE test_demo
(
    id          int(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
    dept_id     int(0) NULL DEFAULT NULL COMMENT '部门id',
    user_id     int(0) NULL DEFAULT NULL COMMENT '用户id',
    order_num   int(0) NULL DEFAULT 0 COMMENT '排序号',
    test_key    varchar(255) NULL DEFAULT NULL COMMENT 'key键',
    value       varchar(255) NULL DEFAULT NULL COMMENT '值',
    version     int(0) NULL DEFAULT 0 COMMENT '版本',
    create_time datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
    create_by   varchar(64) NULL DEFAULT NULL COMMENT '创建人',
    update_time datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
    update_by   varchar(64) NULL DEFAULT NULL COMMENT '更新人',
    del_flag    int(0) NULL DEFAULT NULL COMMENT '删除标志',
    PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB COMMENT = '测试单表';
DROP TABLE if EXISTS test_tree;
CREATE TABLE test_tree
(
    id          int(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
    parent_id   int(0) NULL DEFAULT 0 COMMENT '父id',
    dept_id     int(0) NULL DEFAULT NULL COMMENT '部门id',
    user_id     int(0) NULL DEFAULT NULL COMMENT '用户id',
    tree_name   varchar(255) NULL DEFAULT NULL COMMENT '值',
    version     int(0) NULL DEFAULT 0 COMMENT '版本',
    create_time datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
    create_by   varchar(64) NULL DEFAULT NULL COMMENT '创建人',
    update_time datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
    update_by   varchar(64) NULL DEFAULT NULL COMMENT '更新人',
    del_flag    int(0) NULL DEFAULT NULL COMMENT '删除标志',
    PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB COMMENT = '测试树表';
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (5, '测试菜单', 0, 5, 'demo', NULL, 1, 0, 'M', '0', '0', NULL, 'star', 'admin', '2021-05-30 00:34:26', NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1500, '测试单表', 5, 1, 'demo', 'demo/demo/index', 1, 0, 'C', '0', '0', 'demo:demo:list', '#', 'admin', '2021-05-30 00:39:23', '', NULL, '测试单表菜单');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1501, '测试单表查询', 1500, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:query', '#', 'admin', '2021-05-30 00:39:23', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1502, '测试单表新增', 1500, 2, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:add', '#', 'admin', '2021-05-30 00:39:23', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1503, '测试单表修改', 1500, 3, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:edit', '#', 'admin', '2021-05-30 00:39:23', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1504, '测试单表删除', 1500, 4, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:remove', '#', 'admin', '2021-05-30 00:39:23', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1505, '测试单表导出', 1500, 5, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:export', '#', 'admin', '2021-05-30 00:39:23', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1506, '测试树表', 5, 1, 'tree', 'demo/tree/index', 1, 0, 'C', '0', '0', 'demo:tree:list', '#', 'admin', '2021-05-30 00:39:30', '', NULL, '测试树表菜单');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1507, '测试树表查询', 1506, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:query', '#', 'admin', '2021-05-30 00:39:30', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1508, '测试树表新增', 1506, 2, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:add', '#', 'admin', '2021-05-30 00:39:30', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1509, '测试树表修改', 1506, 3, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:edit', '#', 'admin', '2021-05-30 00:39:30', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1510, '测试树表删除', 1506, 4, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:remove', '#', 'admin', '2021-05-30 00:39:30', '', NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1511, '测试树表导出', 1506, 5, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:export', '#', 'admin', '2021-05-30 00:39:30', '', NULL, '');
INSERT INTO sys_role(role_id, role_name, role_key, role_sort, data_scope, menu_check_strictly, dept_check_strictly, status, del_flag, create_by, create_time, update_by, update_time, remark) VALUES (3, '本部门及以下', 'test1', 3, '4', 1, 1, '0', '0', 'admin', '2021-05-08 22:31:37', 'admin', '2021-05-08 22:32:03', NULL);
INSERT INTO sys_role(role_id, role_name, role_key, role_sort, data_scope, menu_check_strictly, dept_check_strictly, status, del_flag, create_by, create_time, update_by, update_time, remark) VALUES (4, '仅本人', 'test2', 4, '5', 1, 1, '0', '0', 'admin', '2021-05-30 01:14:52', 'admin', '2021-05-30 01:18:38', NULL);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 5);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 100);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 101);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 102);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 103);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 104);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 105);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 106);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 107);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 108);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 500);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 501);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1001);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1002);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1003);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1004);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1005);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1006);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1007);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1008);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1009);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1010);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1011);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1012);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1013);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1014);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1015);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1016);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1017);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1018);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1019);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1020);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1021);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1022);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1023);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1024);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1025);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1026);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1027);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1028);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1029);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1030);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1031);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1032);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1033);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1034);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1035);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1036);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1037);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1038);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1039);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1040);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1041);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1042);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1043);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1044);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1045);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1500);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1501);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1502);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1503);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1504);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1505);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1506);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1507);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1508);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1509);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1510);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1511);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 5);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1500);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1501);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1502);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1503);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1504);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1505);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1506);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1507);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1508);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1509);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1510);
INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1511);
INSERT INTO sys_user(user_id, dept_id, user_name, nick_name, user_type, email, phonenumber, sex, avatar, password, status, del_flag, login_ip, login_date, create_by, create_time, update_by, update_time, remark) VALUES (3, 108, 'test', '本部门及以下 å¯†ç 666', '00', '', '', '0', '', '$2a$10$M6tZRpUZbWKq11O/z6YISePQc./Jhru8E18mmVJTr9aV8whzfjacC', '0', '0', '127.0.0.1', '2021-05-30 02:00:37', 'admin', '2021-04-22 09:50:41', 'test', '2021-05-30 02:00:37', NULL);
INSERT INTO sys_user(user_id, dept_id, user_name, nick_name, user_type, email, phonenumber, sex, avatar, password, status, del_flag, login_ip, login_date, create_by, create_time, update_by, update_time, remark) VALUES (4, 102, 'test1', '仅本人 å¯†ç 666', '00', '', '', '0', '', '$2a$10$yBSXp5Ba1m402cxXTPSy4eXUO8CXCGvXfquNVP/XMWwZ8nf9GaoMy', '0', '0', '127.0.0.1', '2021-05-30 01:48:03', 'admin', '2021-05-30 01:16:02', 'test1', '2021-05-30 01:48:03', NULL);
INSERT INTO sys_user_role(user_id, role_id) VALUES (3, 3);
INSERT INTO sys_user_role(user_id, role_id) VALUES (4, 4);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (1, 102, 4, 1, '测试数据权限', '测试', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (2, 102, 3, 2, '子节点1', '111', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (3, 102, 3, 3, '子节点2', '222', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (4, 108, 4, 4, '测试数据', 'demo', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (5, 108, 3, 13, '子节点11', '1111', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (6, 108, 3, 12, '子节点22', '2222', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (7, 108, 3, 11, '子节点33', '3333', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (8, 108, 3, 10, '子节点44', '4444', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (9, 108, 3, 9, '子节点55', '5555', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (10, 108, 3, 8, '子节点66', '6666', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (11, 108, 3, 7, '子节点77', '7777', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (12, 108, 3, 6, '子节点88', '8888', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (13, 108, 3, 5, '子节点99', '9999', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (1, 0, 102, 4, '测试数据权限', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (2, 1, 102, 3, '子节点1', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (3, 2, 102, 3, '子节点2', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (4, 0, 108, 4, '测试树1', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (5, 4, 108, 3, '子节点11', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (6, 4, 108, 3, '子节点22', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (7, 4, 108, 3, '子节点33', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (8, 5, 108, 3, '子节点44', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (9, 6, 108, 3, '子节点55', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (10, 7, 108, 3, '子节点66', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (11, 7, 108, 3, '子节点77', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (12, 10, 108, 3, '子节点88', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);
INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (13, 10, 108, 3, '子节点99', 0, '2021-06-01 10:00:00', 'admin', NULL, NULL, 0);