diff --git a/README.md b/README.md index 4597c708f..96ca78d1f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## 平台简介 -**芋道** 是基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) **重构**,一套**全部开源**的**企业级**的快速开发平台,毫无保留给个人及企业免费使用。 +**芋道**,一套**全部开源**的**企业级**的快速开发平台,毫无保留给个人及企业免费使用。 > 有任何问题,或者想要的功能,可以在 _Issues_ 中提给艿艿。 @@ -17,39 +17,63 @@ * 基础设施 * 研发工具 +> 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。 +> +> 额外新增的功能,我们使用 🚀 标记。 + +🙂 所有功能,都通过 **单元测试** 保证高质量。 + ### 系统功能 -1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置 -1. 在线用户:当前系统中活跃用户状态监控 -1. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分 -1. 菜单管理:配置系统菜单,操作权限,按钮权限标识等 -1. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 -1. 岗位管理:配置系统用户所属担任职务 -1. 字典管理:对系统中经常使用的一些较为固定的数据进行维护 -1. 通知公告:系统通知公告信息发布维护 -1. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询 -1. 登录日志:系统登录日志记录查询包含登录异常 + +| | 功能 | 描述 | +| --- | --- | --- | +| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 | +| | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 | +| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | +| | 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等 | +| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 | +| | 岗位管理 | 配置系统用户所属担任职务 | +| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | +| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、云片等主流短信平台 | +| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | +| | 登录日志 | 系统登录日志记录查询,包含登录异常 | +| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 | +| | 通知公告 | 系统通知公告信息发布维护 | + +计划新增功能: +* 邮件 +* 钉钉、飞书等通知 ### 基础设施 -1. 配置管理:对系统动态配置常用参数 -1. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志 -1. API 日志:包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 -1. MySQL 监控:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 -1. Redis 监控:监控 Redis 数据库的使用情况,使用的 Redis Key 管理 -1. Java 监控:基于 Spring Boot Admin 实现 Java 应用的监控 -1. 链路追踪:基于 SkyWalking 实现性能监控,特别是链路的追踪 -1. 分布式锁:基于 Redis 实现分布式锁,满足并发场景 -1. 幂等组件:基于 Redis 实现幂等组件,解决重复请求问题 -1. 服务保障:基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 -1. 日志服务:轻量级日志中心,查看远程服务器的日志 +| | 功能 | 描述 | +| --- | --- | --- | +| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 | +| | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 | +| 🚀 | 文件服务 | 支持本地文件存储,同时支持兼容 Amazon S3 协议的云服务、开源组件 | +| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 | +| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 | +| | Redis 监控 |监控 Redis 数据库的使用情况,使用的 Redis Key 管理 | +| 🚀 |Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 | +| 🚀 | 链路追踪 | 基于 SkyWalking 实现性能监控,特别是链路的追踪 | +| 🚀 | 分布式锁 | 基于 Redis 实现分布式锁,满足并发场景 | +| 🚀 | 幂等组件 | 基于 Redis 实现幂等组件,解决重复请求问题 | +| 🚀 | 服务保障 | 基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 | +| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 | +| 🚀 | 单元测试 |基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 | + +计划新增: +* 工作流 ### 研发工具 -1. 表单构建:拖动表单元素生成相应的 HTML 代码 -1. 代码生成:前后端代码的生成(Java、Vue、SQL),支持 CRUD 下载 -1. 系统接口:基于 Swagger 自动生成相关的 RESTful API 接口文档 -1. 数据库文档:基于 Screw 自动生成数据库文档 +| | 功能 | 描述 | +| --- | --- | --- | +| 🚀 | 代码生成 |前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 | +| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 | +| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 | +| | 表单构建 | 拖动表单元素生成相应的 HTML 代码 | ## 在线体验 @@ -63,14 +87,15 @@ ## 技术栈 -**后端** +### 后端 | 框架 | 说明 | 版本 | 学习指南 | | --- | --- | --- | --- | | [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.4.2 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | | [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 | | | [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.4 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | -| [MyBatis-Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | +| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | +| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | | [Redis](https://redis.io/) | key-value 数据库 | 5.0 | | | [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.1.46 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | | [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.4.2 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | @@ -78,14 +103,16 @@ | [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.1.7 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | | [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) | | [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | -| [Resilience4j](https://github.com/quartz-scheduler) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) | +| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) | | [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) | -| [Spring Boot Admin](https://github.com/skywalking) | Spring Boot 监控平台 | 8.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | +| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 8.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | | [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.11.4 | | | [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) | -| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码| 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) | +| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) | +| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.7.0 | - | +| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 3.6.28 | - | -**前端** +### 前端 | 框架 | 说明 | 版本 | | --- | --- | --- | @@ -125,7 +152,7 @@ - + - diff --git a/lombok.config b/lombok.config new file mode 100644 index 000000000..c6488faea --- /dev/null +++ b/lombok.config @@ -0,0 +1,4 @@ +config.stopBubbling = true +lombok.tostring.callsuper=true +lombok.equalsandhashcode.callsuper=true +lombok.accessors.chain=true diff --git a/pom.xml b/pom.xml index ffb61c14c..f3acf5108 100644 --- a/pom.xml +++ b/pom.xml @@ -22,14 +22,16 @@ ${java.version} 3.8.0 - 2.4.2 + 2.4.4 3.0.2 + 1.5.22 5.1.46 1.2.4 - 3.4.1 - 3.14.1 + 3.4.2 + 3.3.2 + 3.15.1 1.7.0 @@ -42,10 +44,16 @@ 1.16.14 1.4.1.Final - 5.5.6 + 5.6.1 2.2.7 2.2 1.0.5 + 7.2.6.RELEASE + 0.1.16 + + 4.5.18 + 2.1.0 + 1.2.7 @@ -101,8 +109,21 @@ mapstruct org.mapstruct + + guava + com.google.guava + + + swagger-annotations + io.swagger + + + io.swagger + swagger-annotations + ${swagger-annotations.version} + @@ -120,6 +141,11 @@ mybatis-plus-boot-starter ${mybatis-plus.version} + + com.baomidou + dynamic-datasource-spring-boot-starter + ${dynamic-datasource.version} + org.redisson @@ -145,6 +171,12 @@ com.baomidou lock4j-redisson-spring-boot-starter ${lock4j.version} + + + redisson-spring-boot-starter + org.redisson + + @@ -181,6 +213,12 @@ org.springframework.boot spring-boot-starter-test test + + + asm + org.ow2.asm + + @@ -192,14 +230,14 @@ com.github.fppt jedis-mock - 0.1.16 + ${jedis-mock.version} test uk.co.jemos.podam podam - 7.2.6.RELEASE + ${podam.version} test @@ -215,6 +253,12 @@ mapstruct ${mapstruct.version} + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + true + org.mapstruct mapstruct-jdk8 @@ -223,27 +267,7 @@ cn.hutool - hutool-core - ${hutool.version} - - - cn.hutool - hutool-extra - ${hutool.version} - - - cn.hutool - hutool-captcha - ${hutool.version} - - - cn.hutool - hutool-http - ${hutool.version} - - - cn.hutool - hutool-crypto + hutool-all ${hutool.version} @@ -265,6 +289,27 @@ ${screw.version} + + + + + com.yunpian.sdk + yunpian-java-sdk + ${yunpian-java-sdk.version} + + + + com.aliyun + aliyun-java-sdk-core + ${aliyun-java-sdk-core.version} + + + com.aliyun + aliyun-java-sdk-dysmsapi + ${aliyun-java-sdk-dysmsapi.version} + + + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java deleted file mode 100644 index 26d664f6e..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 数据权限过滤注解 - * - * @author ruoyi - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface DataScope { - /** - * 部门表的别名 - */ - public String deptAlias() default ""; - - /** - * 用户表的别名 - */ - public String userAlias() default ""; -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScopeAspect.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScopeAspect.java deleted file mode 100644 index cc01b9422..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScopeAspect.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.ruoyi.framework.aspectj; - -import java.lang.reflect.Method; - -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.Signature; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.stereotype.Component; -import com.ruoyi.common.annotation.DataScope; -import com.ruoyi.common.core.domain.BaseEntity; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.web.service.TokenService; - -/** - * 数据过滤处理 - * - * @author ruoyi - */ -@Aspect -@Component -public class DataScopeAspect { - /** - * 全部数据权限 - */ - public static final String DATA_SCOPE_ALL = "1"; - - /** - * 自定数据权限 - */ - public static final String DATA_SCOPE_CUSTOM = "2"; - - /** - * 部门数据权限 - */ - public static final String DATA_SCOPE_DEPT = "3"; - - /** - * 部门及以下数据权限 - */ - public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; - - /** - * 仅本人数据权限 - */ - public static final String DATA_SCOPE_SELF = "5"; - - /** - * 数据权限过滤关键字 - */ - public static final String DATA_SCOPE = "dataScope"; - - // 配置织入点 - @Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)") - public void dataScopePointCut() { - } - - @Before("dataScopePointCut()") - public void doBefore(JoinPoint point) throws Throwable { - handleDataScope(point); - } - - protected void handleDataScope(final JoinPoint joinPoint) { - // 获得注解 - DataScope controllerDataScope = getAnnotationLog(joinPoint); - if (controllerDataScope == null) { - return; - } - // 获取当前的用户 - LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest()); - if (StringUtils.isNotNull(loginUser)) { - SysUser currentUser = loginUser.getUser(); - // 如果是超级管理员,则不过滤数据 - if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) { - dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), - controllerDataScope.userAlias()); - } - } - } - - /** - * 数据范围过滤 - * - * @param joinPoint 切点 - * @param user 用户 - * @param userAlias 别名 - */ - public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) { - StringBuilder sqlString = new StringBuilder(); - - for (SysRole role : user.getRoles()) { - String dataScope = role.getDataScope(); - if (DATA_SCOPE_ALL.equals(dataScope)) { - sqlString = new StringBuilder(); - break; - } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { - sqlString.append(StringUtils.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(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); - } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { - sqlString.append(StringUtils.format( - " 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 (StringUtils.isNotBlank(userAlias)) { - sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); - } else { - // 数据权限为仅本人且没有userAlias别名不查询任何数据 - sqlString.append(" OR 1=0 "); - } - } - } - - if (StringUtils.isNotBlank(sqlString.toString())) { - Object params = joinPoint.getArgs()[0]; - if (StringUtils.isNotNull(params) && params instanceof BaseEntity) { - BaseEntity baseEntity = (BaseEntity) params; - baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); - } - } - } - - /** - * 是否存在注解,如果存在就获取 - */ - private DataScope getAnnotationLog(JoinPoint joinPoint) { - Signature signature = joinPoint.getSignature(); - MethodSignature methodSignature = (MethodSignature) signature; - Method method = methodSignature.getMethod(); - - if (method != null) { - return method.getAnnotation(DataScope.class); - } - return null; - } -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java deleted file mode 100644 index 11b0d579c..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.ruoyi.common.enums.DataSourceType; - -/** - * 自定义多数据源切换注解 - *

- * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 - * - * @author ruoyi - */ -@Target({ElementType.METHOD, ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -public @interface DataSource { - /** - * 切换数据源名称 - */ - public DataSourceType value() default DataSourceType.MASTER; -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSourceAspect.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSourceAspect.java deleted file mode 100644 index 020493d2d..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSourceAspect.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.ruoyi.framework.aspectj; - -import java.util.Objects; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; -import com.ruoyi.common.annotation.DataSource; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder; - -/** - * 多数据源处理 - * - * @author ruoyi - */ -@Aspect -@Order(1) -@Component -public class DataSourceAspect { - protected Logger logger = LoggerFactory.getLogger(getClass()); - - @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)" - + "|| @within(com.ruoyi.common.annotation.DataSource)") - public void dsPointCut() { - - } - - @Around("dsPointCut()") - public Object around(ProceedingJoinPoint point) throws Throwable { - DataSource dataSource = getDataSource(point); - - if (StringUtils.isNotNull(dataSource)) { - DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); - } - - try { - return point.proceed(); - } finally { - // 销毁数据源 在执行方法之后 - DynamicDataSourceContextHolder.clearDataSourceType(); - } - } - - /** - * 获取需要切换的数据源 - */ - public DataSource getDataSource(ProceedingJoinPoint point) { - MethodSignature signature = (MethodSignature) point.getSignature(); - DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); - if (Objects.nonNull(dataSource)) { - return dataSource; - } - - return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); - } -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSourceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSourceType.java deleted file mode 100644 index 0d945be54..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSourceType.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ruoyi.common.enums; - -/** - * 数据源 - * - * @author ruoyi - */ -public enum DataSourceType -{ - /** - * 主库 - */ - MASTER, - - /** - * 从库 - */ - SLAVE -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DynamicDataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DynamicDataSource.java deleted file mode 100644 index f60b35cb6..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DynamicDataSource.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.ruoyi.framework.datasource; - -import java.util.Map; -import javax.sql.DataSource; - -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; - -/** - * 动态数据源 - * - * @author ruoyi - */ -public class DynamicDataSource extends AbstractRoutingDataSource { - public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) { - super.setDefaultTargetDataSource(defaultTargetDataSource); - super.setTargetDataSources(targetDataSources); - super.afterPropertiesSet(); - } - - @Override - protected Object determineCurrentLookupKey() { - return DynamicDataSourceContextHolder.getDataSourceType(); - } -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DynamicDataSourceContextHolder.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DynamicDataSourceContextHolder.java deleted file mode 100644 index 37a5f8e58..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DynamicDataSourceContextHolder.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.ruoyi.framework.datasource; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 数据源切换处理 - * - * @author ruoyi - */ -public class DynamicDataSourceContextHolder { - public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class); - - /** - * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本, - * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 - */ - private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); - - /** - * 设置数据源的变量 - */ - public static void setDataSourceType(String dsType) { - log.info("切换到{}数据源", dsType); - CONTEXT_HOLDER.set(dsType); - } - - /** - * 获得数据源的变量 - */ - public static String getDataSourceType() { - return CONTEXT_HOLDER.get(); - } - - /** - * 清空数据源变量 - */ - public static void clearDataSourceType() { - CONTEXT_HOLDER.remove(); - } -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/DruidConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/DruidConfig.java deleted file mode 100644 index 7e9f4b03f..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/config/DruidConfig.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.ruoyi.framework.config; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.sql.DataSource; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; -import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; -import com.alibaba.druid.util.Utils; -import com.ruoyi.common.enums.DataSourceType; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.config.properties.DruidProperties; -import com.ruoyi.framework.datasource.DynamicDataSource; - -/** - * druid 配置多数据源 - * - * @author ruoyi - */ -@Configuration -public class DruidConfig { - @Bean - @ConfigurationProperties("spring.datasource.druid.master") - public DataSource masterDataSource(DruidProperties druidProperties) { - DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); - return druidProperties.dataSource(dataSource); - } - - @Bean - @ConfigurationProperties("spring.datasource.druid.slave") - @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true") - public DataSource slaveDataSource(DruidProperties druidProperties) { - DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); - return druidProperties.dataSource(dataSource); - } - - @Bean(name = "dynamicDataSource") - @Primary - public DynamicDataSource dataSource(DataSource masterDataSource) { - Map targetDataSources = new HashMap<>(); - targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource); - setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); - return new DynamicDataSource(masterDataSource, targetDataSources); - } - - /** - * 设置数据源 - * - * @param targetDataSources 备选数据源集合 - * @param sourceName 数据源名称 - * @param beanName bean名称 - */ - public void setDataSource(Map targetDataSources, String sourceName, String beanName) { - try { - DataSource dataSource = SpringUtils.getBean(beanName); - targetDataSources.put(sourceName, dataSource); - } catch (Exception e) { - } - } - - /** - * 去除监控页面底部的广告 - */ - @SuppressWarnings({"rawtypes", "unchecked"}) - @Bean - @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") - public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) { - // 获取web监控页面的参数 - DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); - // 提取common.js的配置路径 - String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; - String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); - final String filePath = "support/http/resources/js/common.js"; - // 创建filter进行过滤 - Filter filter = new Filter() { - @Override - public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - chain.doFilter(request, response); - // 重置缓冲区,响应头不会被重置 - response.resetBuffer(); - // 获取common.js - String text = Utils.readFromResource(filePath); - // 正则替换banner, 除去底部的广告信息 - text = text.replaceAll("
", ""); - text = text.replaceAll("powered.*?shrek.wang", ""); - response.getWriter().write(text); - } - - @Override - public void destroy() { - } - }; - FilterRegistrationBean registrationBean = new FilterRegistrationBean(); - registrationBean.setFilter(filter); - registrationBean.addUrlPatterns(commonJsPattern); - return registrationBean; - } -} diff --git a/ruoyi-common/src/main/resources/application-druid.yml b/ruoyi-common/src/main/resources/application-druid.yml deleted file mode 100644 index 6057ce24f..000000000 --- a/ruoyi-common/src/main/resources/application-druid.yml +++ /dev/null @@ -1,37 +0,0 @@ -# 数据源配置 -spring: - datasource: - type: com.alibaba.druid.pool.DruidDataSource - driverClassName: com.mysql.cj.jdbc.Driver - druid: - # 主库数据源 - master: - url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - username: root - password: password - # 从库数据源 - slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 - # 最大连接池数量 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL - testWhileIdle: true - testOnBorrow: false - testOnReturn: false diff --git a/ruoyi-ui/.env.demo1024 b/ruoyi-ui/.env.demo1024 new file mode 100644 index 000000000..ffeadbf8c --- /dev/null +++ b/ruoyi-ui/.env.demo1024 @@ -0,0 +1,7 @@ +NODE_ENV = production + +# 测试环境配置 +ENV = 'staging' + +# 芋道管理系统/测试环境 +VUE_APP_BASE_API = 'http://127.0.0.1:48080' diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 46718e1b0..1249d16b3 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -8,6 +8,7 @@ "dev": "vue-cli-service serve", "build:prod": "vue-cli-service build", "build:stage": "vue-cli-service build --mode staging", + "build:demo1024": "vue-cli-service build --mode demo1024", "preview": "node build/index.js --preview", "lint": "eslint --ext .js,.vue src" }, diff --git a/ruoyi-ui/src/api/infra/dbDoc.js b/ruoyi-ui/src/api/infra/dbDoc.js index de54981d1..015c6d71d 100644 --- a/ruoyi-ui/src/api/infra/dbDoc.js +++ b/ruoyi-ui/src/api/infra/dbDoc.js @@ -8,3 +8,19 @@ export function exportHtml() { responseType: 'blob' }) } + +export function exportWord() { + return request({ + url: '/infra/db-doc/export-word', + method: 'get', + responseType: 'blob' + }) +} + +export function exportMarkdown() { + return request({ + url: '/infra/db-doc/export-markdown', + method: 'get', + responseType: 'blob' + }) +} diff --git a/ruoyi-ui/src/api/infra/file.js b/ruoyi-ui/src/api/infra/file.js new file mode 100644 index 000000000..2aeda2e90 --- /dev/null +++ b/ruoyi-ui/src/api/infra/file.js @@ -0,0 +1,18 @@ +import request from '@/utils/request' + +// 删除文件 +export function deleteFile(id) { + return request({ + url: '/infra/file/delete?id=' + id, + method: 'delete' + }) +} + +// 获得文件分页 +export function getFilePage(query) { + return request({ + url: '/infra/file/page', + method: 'get', + params: query + }) +} diff --git a/ruoyi-ui/src/api/system/dept.js b/ruoyi-ui/src/api/system/dept.js index c22f0f4a8..d8c59cf9a 100644 --- a/ruoyi-ui/src/api/system/dept.js +++ b/ruoyi-ui/src/api/system/dept.js @@ -46,7 +46,7 @@ export function addDept(data) { export function updateDept(data) { return request({ url: '/system/dept/update', - method: 'post', + method: 'put', data: data }) } @@ -55,6 +55,6 @@ export function updateDept(data) { export function delDept(id) { return request({ url: '/system/dept/delete?id=' + id, - method: 'post' + method: 'delete' }) } diff --git a/ruoyi-ui/src/api/system/dict/data.js b/ruoyi-ui/src/api/system/dict/data.js index c29b2f81f..00e614b15 100644 --- a/ruoyi-ui/src/api/system/dict/data.js +++ b/ruoyi-ui/src/api/system/dict/data.js @@ -38,7 +38,7 @@ export function addData(data) { export function updateData(data) { return request({ url: '/system/dict-data/update', - method: 'post', + method: 'put', data: data }) } @@ -47,7 +47,7 @@ export function updateData(data) { export function delData(dictCode) { return request({ url: '/system/dict-data/delete?id=' + dictCode, - method: 'post' + method: 'delete' }) } diff --git a/ruoyi-ui/src/api/system/dict/type.js b/ruoyi-ui/src/api/system/dict/type.js index a1423f1d6..9fe10d418 100644 --- a/ruoyi-ui/src/api/system/dict/type.js +++ b/ruoyi-ui/src/api/system/dict/type.js @@ -30,7 +30,7 @@ export function addType(data) { export function updateType(data) { return request({ url: '/system/dict-type/update', - method: 'post', + method: 'put', data: data }) } @@ -39,7 +39,7 @@ export function updateType(data) { export function delType(dictId) { return request({ url: '/system/dict-type/delete?id=' + dictId, - method: 'post' + method: 'delete' }) } diff --git a/ruoyi-ui/src/api/system/errorCode.js b/ruoyi-ui/src/api/system/errorCode.js new file mode 100644 index 000000000..29546b7f4 --- /dev/null +++ b/ruoyi-ui/src/api/system/errorCode.js @@ -0,0 +1,54 @@ +import request from '@/utils/request' + +// 创建错误码 +export function createErrorCode(data) { + return request({ + url: '/system/error-code/create', + method: 'post', + data: data + }) +} + +// 更新错误码 +export function updateErrorCode(data) { + return request({ + url: '/system/error-code/update', + method: 'put', + data: data + }) +} + +// 删除错误码 +export function deleteErrorCode(id) { + return request({ + url: '/system/error-code/delete?id=' + id, + method: 'delete' + }) +} + +// 获得错误码 +export function getErrorCode(id) { + return request({ + url: '/system/error-code/get?id=' + id, + method: 'get' + }) +} + +// 获得错误码分页 +export function getErrorCodePage(query) { + return request({ + url: '/system/error-code/page', + method: 'get', + params: query + }) +} + +// 导出错误码 Excel +export function exportErrorCodeExcel(query) { + return request({ + url: '/system/error-code/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} diff --git a/ruoyi-ui/src/api/system/menu.js b/ruoyi-ui/src/api/system/menu.js index fb3fa6e98..b378b01d9 100644 --- a/ruoyi-ui/src/api/system/menu.js +++ b/ruoyi-ui/src/api/system/menu.js @@ -38,7 +38,7 @@ export function addMenu(data) { export function updateMenu(data) { return request({ url: '/system/menu/update', - method: 'post', + method: 'put', data: data }) } @@ -47,6 +47,6 @@ export function updateMenu(data) { export function delMenu(id) { return request({ url: '/system/menu/delete?id=' + id, - method: 'post' + method: 'delete' }) } diff --git a/ruoyi-ui/src/api/system/notice.js b/ruoyi-ui/src/api/system/notice.js index 744bba745..b8c7cf709 100644 --- a/ruoyi-ui/src/api/system/notice.js +++ b/ruoyi-ui/src/api/system/notice.js @@ -30,7 +30,7 @@ export function addNotice(data) { export function updateNotice(data) { return request({ url: '/system/notice/update', - method: 'post', + method: 'put', data: data }) } @@ -39,6 +39,6 @@ export function updateNotice(data) { export function delNotice(noticeId) { return request({ url: '/system/notice/delete?id=' + noticeId, - method: 'post' + method: 'delete' }) } diff --git a/ruoyi-ui/src/api/system/post.js b/ruoyi-ui/src/api/system/post.js index cb1dfc3e5..3ef4a9906 100644 --- a/ruoyi-ui/src/api/system/post.js +++ b/ruoyi-ui/src/api/system/post.js @@ -38,7 +38,7 @@ export function addPost(data) { export function updatePost(data) { return request({ url: '/system/post/update', - method: 'post', + method: 'put', data: data }) } @@ -47,7 +47,7 @@ export function updatePost(data) { export function delPost(postId) { return request({ url: '/system/post/delete?id=' + postId, - method: 'post' + method: 'delete' }) } diff --git a/ruoyi-ui/src/api/system/role.js b/ruoyi-ui/src/api/system/role.js index 36edcc2dd..27bb0500b 100644 --- a/ruoyi-ui/src/api/system/role.js +++ b/ruoyi-ui/src/api/system/role.js @@ -38,7 +38,7 @@ export function addRole(data) { export function updateRole(data) { return request({ url: '/system/role/update', - method: 'post', + method: 'put', data: data }) } @@ -51,7 +51,7 @@ export function changeRoleStatus(id, status) { } return request({ url: '/system/role/update-status', - method: 'post', + method: 'put', data: data }) } @@ -60,7 +60,7 @@ export function changeRoleStatus(id, status) { export function delRole(roleId) { return request({ url: '/system/role/delete?id=' + roleId, - method: 'post' + method: 'delete' }) } diff --git a/ruoyi-ui/src/api/system/sms/smsChannel.js b/ruoyi-ui/src/api/system/sms/smsChannel.js new file mode 100644 index 000000000..4e38de05f --- /dev/null +++ b/ruoyi-ui/src/api/system/sms/smsChannel.js @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +// 创建短信渠道 +export function createSmsChannel(data) { + return request({ + url: '/system/sms-channel/create', + method: 'post', + data: data + }) +} + +// 更新短信渠道 +export function updateSmsChannel(data) { + return request({ + url: '/system/sms-channel/update', + method: 'put', + data: data + }) +} + +// 删除短信渠道 +export function deleteSmsChannel(id) { + return request({ + url: '/system/sms-channel/delete?id=' + id, + method: 'delete' + }) +} + +// 获得短信渠道 +export function getSmsChannel(id) { + return request({ + url: '/system/sms-channel/get?id=' + id, + method: 'get' + }) +} + +// 获得短信渠道分页 +export function getSmsChannelPage(query) { + return request({ + url: '/system/sms-channel/page', + method: 'get', + params: query + }) +} + +// 获得短信渠道精简列表 +export function getSimpleSmsChannels() { + return request({ + url: '/system/sms-channel/list-all-simple', + method: 'get', + }) +} diff --git a/ruoyi-ui/src/api/system/sms/smsLog.js b/ruoyi-ui/src/api/system/sms/smsLog.js new file mode 100644 index 000000000..8a9083b71 --- /dev/null +++ b/ruoyi-ui/src/api/system/sms/smsLog.js @@ -0,0 +1,20 @@ +import request from '@/utils/request' + +// 获得短信日志分页 +export function getSmsLogPage(query) { + return request({ + url: '/system/sms-log/page', + method: 'get', + params: query + }) +} + +// 导出短信日志 Excel +export function exportSmsLogExcel(query) { + return request({ + url: '/system/sms-log/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} diff --git a/ruoyi-ui/src/api/system/sms/smsTemplate.js b/ruoyi-ui/src/api/system/sms/smsTemplate.js new file mode 100644 index 000000000..d6d933044 --- /dev/null +++ b/ruoyi-ui/src/api/system/sms/smsTemplate.js @@ -0,0 +1,64 @@ +import request from '@/utils/request' + +// 创建短信模板 +export function createSmsTemplate(data) { + return request({ + url: '/system/sms-template/create', + method: 'post', + data: data + }) +} + +// 更新短信模板 +export function updateSmsTemplate(data) { + return request({ + url: '/system/sms-template/update', + method: 'put', + data: data + }) +} + +// 删除短信模板 +export function deleteSmsTemplate(id) { + return request({ + url: '/system/sms-template/delete?id=' + id, + method: 'delete' + }) +} + +// 获得短信模板 +export function getSmsTemplate(id) { + return request({ + url: '/system/sms-template/get?id=' + id, + method: 'get' + }) +} + +// 获得短信模板分页 +export function getSmsTemplatePage(query) { + return request({ + url: '/system/sms-template/page', + method: 'get', + params: query + }) +} + +// 创建短信模板 +export function sendSms(data) { + return request({ + url: '/system/sms-template/send-sms', + method: 'post', + data: data + }) +} + +// 导出短信模板 Excel +export function exportSmsTemplateExcel(query) { + return request({ + url: '/system/sms-template/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} + diff --git a/ruoyi-ui/src/api/system/user.js b/ruoyi-ui/src/api/system/user.js index 7676e2bcb..cf0f007d5 100644 --- a/ruoyi-ui/src/api/system/user.js +++ b/ruoyi-ui/src/api/system/user.js @@ -31,7 +31,7 @@ export function addUser(data) { export function updateUser(data) { return request({ url: '/system/user/update', - method: 'post', + method: 'put', data: data }) } @@ -62,7 +62,7 @@ export function resetUserPwd(id, password) { } return request({ url: '/system/user/update-password', - method: 'post', + method: 'put', data: data }) } @@ -75,7 +75,7 @@ export function changeUserStatus(id, status) { } return request({ url: '/system/user/update-status', - method: 'post', + method: 'put', data: data }) } @@ -83,7 +83,7 @@ export function changeUserStatus(id, status) { // 查询用户个人信息 export function getUserProfile() { return request({ - url: '/system/user/profile', + url: '/system/user/profile/get', method: 'get' }) } @@ -91,7 +91,7 @@ export function getUserProfile() { // 修改用户个人信息 export function updateUserProfile(data) { return request({ - url: '/system/user/profile', + url: '/system/user/profile/update', method: 'put', data: data }) @@ -104,9 +104,9 @@ export function updateUserPwd(oldPassword, newPassword) { newPassword } return request({ - url: '/system/user/profile/updatePwd', + url: '/system/user/profile/update-password', method: 'put', - params: data + data: data }) } @@ -114,7 +114,7 @@ export function updateUserPwd(oldPassword, newPassword) { export function uploadAvatar(data) { return request({ url: '/system/user/profile/avatar', - method: 'post', + method: 'put', data: data }) } diff --git a/ruoyi-ui/src/main.js b/ruoyi-ui/src/main.js index 91556bf68..e1f067fa1 100644 --- a/ruoyi-ui/src/main.js +++ b/ruoyi-ui/src/main.js @@ -25,7 +25,10 @@ import { download, handleTree, downloadExcel, - downloadZip + downloadWord, + downloadZip, + downloadHtml, + downloadMarkdown, } from "@/utils/ruoyi"; import Pagination from "@/components/Pagination"; // 自定义表格工具扩展 @@ -48,6 +51,9 @@ Vue.prototype.getDictDataLabel = getDictDataLabel Vue.prototype.DICT_TYPE = DICT_TYPE Vue.prototype.download = download Vue.prototype.downloadExcel = downloadExcel +Vue.prototype.downloadWord = downloadWord +Vue.prototype.downloadHtml = downloadHtml +Vue.prototype.downloadMarkdown = downloadMarkdown Vue.prototype.downloadZip = downloadZip Vue.prototype.handleTree = handleTree diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index 82b2b18fa..f7084c59c 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -53,7 +53,7 @@ const user = { getInfo(state.token).then(res => { res = res.data; // 读取 data 数据 const user = res.user - const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; + const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : user.avatar; if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 commit('SET_ROLES', res.roles) commit('SET_PERMISSIONS', res.permissions) diff --git a/ruoyi-ui/src/utils/dict.js b/ruoyi-ui/src/utils/dict.js index 3817a86fe..17d5bd00e 100644 --- a/ruoyi-ui/src/utils/dict.js +++ b/ruoyi-ui/src/utils/dict.js @@ -17,6 +17,11 @@ export const DICT_TYPE = { SYS_OPERATE_TYPE: 'sys_operate_type', SYS_LOGIN_RESULT: 'sys_login_result', SYS_CONFIG_TYPE: 'sys_config_type', + SYS_SMS_CHANNEL_CODE: 'sys_sms_channel_code', + SYS_SMS_TEMPLATE_TYPE: 'sys_sms_template_type', + SYS_SMS_SEND_STATUS: 'sys_sms_send_status', + SYS_SMS_RECEIVE_STATUS: 'sys_sms_receive_status', + SYS_ERROR_CODE_TYPE: 'sys_error_code_type', INF_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type', INF_JOB_STATUS: 'inf_job_status', diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js index 759f03433..c063ec300 100644 --- a/ruoyi-ui/src/utils/request.js +++ b/ruoyi-ui/src/utils/request.js @@ -73,6 +73,18 @@ service.interceptors.response.use(res => { type: 'error' }) return Promise.reject(new Error(msg)) + } else if (code === 901) { + Message({ + type: 'error', + duration: 0, + dangerouslyUseHTMLString: true, + message: '

演示模式,不发进行写操作
' + + '
 
' + + '
参考 https://www.iocoder.cn/Yudao/build-debugger-environment 教程
' + + '
 
' + + '
5 分钟搭建本地环境
', + }) + return Promise.reject(new Error(msg)) } else if (code !== 200) { Notification.error({ title: msg diff --git a/ruoyi-ui/src/utils/ruoyi.js b/ruoyi-ui/src/utils/ruoyi.js index 17f235f22..82f8aecc5 100644 --- a/ruoyi-ui/src/utils/ruoyi.js +++ b/ruoyi-ui/src/utils/ruoyi.js @@ -120,11 +120,26 @@ export function downloadExcel(data, fileName) { download0(data, fileName, 'application/vnd.ms-excel'); } +// 下载 Word 方法 +export function downloadWord(data, fileName) { + download0(data, fileName, 'application/msword'); +} + // 下载 Zip 方法 export function downloadZip(data, fileName) { download0(data, fileName, 'application/zip'); } +// 下载 Html 方法 +export function downloadHtml(data, fileName) { + download0(data, fileName, 'text/html'); +} + +// 下载 Markdown 方法 +export function downloadMarkdown(data, fileName) { + download0(data, fileName, 'text/markdown'); +} + function download0(data, fileName, mineType) { // 创建 blob let blob = new Blob([data], {type: mineType}); diff --git a/ruoyi-ui/src/views/infra/config/index.vue b/ruoyi-ui/src/views/infra/config/index.vue index 592a40f6b..6b880d24c 100644 --- a/ruoyi-ui/src/views/infra/config/index.vue +++ b/ruoyi-ui/src/views/infra/config/index.vue @@ -2,24 +2,12 @@
- + - + @@ -56,7 +44,7 @@ icon="el-icon-plus" size="mini" @click="handleAdd" - v-hasPermi="['infra:config:add']" + v-hasPermi="['infra:config:create']" >新增 @@ -95,31 +83,15 @@ - + diff --git a/ruoyi-ui/src/views/infra/file/index.vue b/ruoyi-ui/src/views/infra/file/index.vue new file mode 100644 index 000000000..5eaf41655 --- /dev/null +++ b/ruoyi-ui/src/views/infra/file/index.vue @@ -0,0 +1,202 @@ + + + diff --git a/ruoyi-ui/src/views/system/dept/index.vue b/ruoyi-ui/src/views/system/dept/index.vue index 5485703ac..0fc5a8733 100644 --- a/ruoyi-ui/src/views/system/dept/index.vue +++ b/ruoyi-ui/src/views/system/dept/index.vue @@ -2,22 +2,11 @@
- + - + @@ -28,24 +17,13 @@ - 新增 + 新增 - + @@ -56,28 +34,12 @@ @@ -119,11 +81,8 @@ - {{dict.label}} + + {{dict.label}} diff --git a/ruoyi-ui/src/views/system/dict/data.vue b/ruoyi-ui/src/views/system/dict/data.vue index 262ea31bb..13d262303 100644 --- a/ruoyi-ui/src/views/system/dict/data.vue +++ b/ruoyi-ui/src/views/system/dict/data.vue @@ -3,31 +3,15 @@ - + - + - + @@ -38,22 +22,12 @@ - 新增 + 新增 - 导出 + 导出 @@ -72,31 +46,16 @@ - + @@ -115,11 +74,7 @@ - {{dict.label}} + {{dict.label}} diff --git a/ruoyi-ui/src/views/system/dict/index.vue b/ruoyi-ui/src/views/system/dict/index.vue index 0e775eaf6..a730e61bf 100644 --- a/ruoyi-ui/src/views/system/dict/index.vue +++ b/ruoyi-ui/src/views/system/dict/index.vue @@ -2,52 +2,19 @@
- + - + - - + + - + 搜索 @@ -57,22 +24,12 @@ - 新增 + 新增 - 导出 + 导出 @@ -96,31 +53,16 @@ - + @@ -133,11 +75,7 @@ - {{dict.label}} + {{dict.label}} @@ -177,7 +115,7 @@ export default { // 状态数据字典 statusOptions: [], // 日期范围 - dateRange: [], + dateRangeCreateTime: [], // 查询参数 queryParams: { pageNo: 1, @@ -211,15 +149,15 @@ export default { /** 查询字典类型列表 */ getList() { this.loading = true; - listType(this.addDateRange(this.queryParams, [ - this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined, - this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined, - ])).then(response => { - this.typeList = response.data.list; - this.total = response.data.total; - this.loading = false; - } - ); + // 处理查询参数 + let params = {...this.queryParams}; + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); + // 执行查询 + listType(params).then(response => { + this.typeList = response.data.list; + this.total = response.data.total; + this.loading = false; + }); }, // 字典状态字典翻译 statusFormat(row, column) { @@ -248,7 +186,7 @@ export default { }, /** 重置按钮操作 */ resetQuery() { - this.dateRange = []; + this.dateRangeCreateTime = []; this.resetForm("queryForm"); this.handleQuery(); }, @@ -304,19 +242,21 @@ export default { }, /** 导出按钮操作 */ handleExport() { - const queryParams = this.addDateRange(this.queryParams, [ - this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined, - this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined, - ]); - this.$confirm('是否确认导出所有类型数据项?', "警告", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning" - }).then(function() { - return exportType(queryParams); - }).then(response => { - this.downloadExcel(response, '数据类型.xls'); - }) + // 处理查询参数 + let params = {...this.queryParams}; + params.pageNo = undefined; + params.pageSize = undefined; + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); + // 执行导出 + this.$confirm('是否确认导出所有字典类型数据项?', "警告", { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning" + }).then(function() { + return exportType(params); + }).then(response => { + this.downloadExcel(response, '字典类型.xls'); + }) } } }; diff --git a/ruoyi-ui/src/views/system/errorCode/index.vue b/ruoyi-ui/src/views/system/errorCode/index.vue new file mode 100644 index 000000000..8ec5aa8fd --- /dev/null +++ b/ruoyi-ui/src/views/system/errorCode/index.vue @@ -0,0 +1,256 @@ + + + diff --git a/ruoyi-ui/src/views/system/loginlog/index.vue b/ruoyi-ui/src/views/system/loginlog/index.vue index 601c9420f..5e572aa94 100644 --- a/ruoyi-ui/src/views/system/loginlog/index.vue +++ b/ruoyi-ui/src/views/system/loginlog/index.vue @@ -2,56 +2,22 @@
- + - + - - - + + + - + 搜索 @@ -61,13 +27,8 @@ - 导出 + 导出 @@ -76,7 +37,7 @@ @@ -95,13 +56,8 @@ - +
diff --git a/ruoyi-ui/src/views/system/menu/index.vue b/ruoyi-ui/src/views/system/menu/index.vue index e2e759eeb..767878e2e 100644 --- a/ruoyi-ui/src/views/system/menu/index.vue +++ b/ruoyi-ui/src/views/system/menu/index.vue @@ -2,22 +2,11 @@
- + - + @@ -28,23 +17,14 @@ - 新增 + 新增 - +