128 Commits

Author SHA1 Message Date
267ff79b0c 😴发布 4.8.2 正式进入维护状态 2023-11-27 13:23:41 +08:00
a6f62ca86f 🎃 发布 4.8.1 稳定性增强 修复部分bug 2023-09-25 10:42:58 +08:00
8a692ed45a 🎃 发布 4.8.0 新增 sms4j 短信融合 2023-07-10 11:06:58 +08:00
6f6ac2c0cf ⚔ 发布 4.7.0 稳定性版本 2023-05-08 09:54:23 +08:00
36ac478624 🎇发布 4.6.0 新增 数据库加解密 与 通用翻译 功能 2023-03-13 10:10:47 +08:00
f196010416 fix 修复 新版本 Redisson 存在与 boot 2.X 的兼容性问题 2023-01-12 15:17:16 +08:00
173862360e 🧧发布 4.5.0 新春版 2023-01-12 09:55:50 +08:00
34574c5bf7 发布 4.4.0 正式版 2022-11-28 14:42:17 +08:00
02e9ac799d 🐬发布 4.3.1 修复了一些问题建议升级 2022-10-24 14:36:47 +08:00
0f237ef7ed fix 修复 日志转换非json数据导致报错 2022-09-13 18:28:55 +08:00
817da4d2b8 fix 修复 用户导入存在则更新不生效 2022-09-13 18:28:44 +08:00
ee48cd7d01 🐣发布 4.3.0 正式版 2022-09-13 16:31:26 +08:00
c5f4dec559 发布 v4.2.0 2022-06-28 22:51:57 +08:00
e0527b3350 Merge remote-tracking branch 'origin/fast' into fast 2022-04-24 14:09:28 +08:00
d5520817bd 发布 4.1.0 2022-04-24 14:09:19 +08:00
7c04240317 fix 修复 数据权限 从 aop 切换到 拦截器 导致获取代理失败问题 2022-03-28 21:03:52 +08:00
2cf283b8c6 发布 4.0.1 2022-03-01 10:37:26 +08:00
0e81a7c342 fix 修复 minio 适配 https 导致的问题 2022-02-18 14:08:21 +08:00
6fa53ebe31 fix 修复 minio 适配 https 导致的问题 2022-02-18 14:08:01 +08:00
356f7ec184 Merge remote-tracking branch 'origin/fast' into fast 2022-02-18 11:38:12 +08:00
400ecdf0ab 发布 4.0.0 2022-02-18 11:37:21 +08:00
28916bd384 fix 修复 数据权限 缓存方法名错误问题 2022-01-26 10:33:49 +00:00
dafb7477f6 update 注释遗漏 老版本数据权限 2021-12-28 14:30:31 +08:00
55e3e93199 发布 v3.5.0-release 正式版 2021-12-28 11:00:10 +08:00
5857db7c5a fix 修复代码生成 导出注解错误 2021-12-13 10:04:33 +08:00
5674d4a618 update 更改前端工程文件版本号
(cherry picked from commit 255b5f2f07)
2021-11-30 11:12:47 +08:00
fd45cdb882 update 补全漏提交文件 2021-11-29 22:07:22 +08:00
c76ab64e8a 发布 v3.4.0 2021-11-29 14:26:23 +08:00
d81377a2ed fix 由于 fast 单体版 代码统一管理 无法排除 quartz 导致运行异常 故优先删除 quartz 相关代码 2021-11-07 20:28:01 +08:00
23cb4eef33 fix 修复通用实体 传参无法接收问题 2021-11-02 22:46:05 +08:00
45e2672e26 fix 修复 xxl-job-admin 部署问题 2021-11-01 13:50:22 +08:00
b98112fd92 fix 修复 SysOss、SysOssConfig 未继承 BaseEntity 基础实体问题 2021-10-31 21:33:54 +08:00
4d12424378 发布 v3.3.0 2021-10-29 09:18:18 +08:00
6def4aa84d fix 修复 多数据源aop语法错误 2021-09-28 14:40:03 +08:00
9351cc4426 发布 v3.2.0 2021-09-28 10:09:53 +08:00
242a74a8ae update 移除无用依赖 2021-09-26 18:04:40 +08:00
ad566e9283 update 回滚 配置检测拦截是否有效SQL 因不通用 2021-09-09 17:41:04 +08:00
5a0136a655 发布 v3.1.0 2021-09-07 14:25:55 +08:00
33033d7d78 !85 fix OssFactory编译报错
Merge pull request !85 from dawn9117/N/A
2021-09-02 08:27:51 +00:00
57ff78d7aa fix OssFactory编译报错 2021-09-02 08:26:17 +00:00
849a131982 !81 fast版 oss上传出错
Merge pull request !81 from 李魁哲/lkz
2021-08-21 02:28:59 +00:00
a66bd96a31 !3 oss上传文件报错
Merge pull request !3 from 李魁哲/N/A
2021-08-21 01:55:23 +00:00
44dfbd24a8 oss上传文件报错 2021-08-21 01:54:56 +00:00
de658c307d !2 21231
Merge pull request !2 from 李魁哲/fast
2021-08-20 10:00:22 +00:00
01f3a94406 Merge branch 'lkz' of gitee.com:lkz9773/RuoYi-Vue-Plus into fast 2021-08-20 10:00:03 +00:00
20d6a893cb fix 修复 excel 导入与 class 未对应问题 2021-08-20 17:02:18 +08:00
4e6057d01e !1 3.00
* update 优化 OSS 模块与上传组件 异常处理
* fix 修复 OSS配置清空被过滤问题
* fix 修复 新版本说明 标签错误
* fix 修复 富文本图片路径错误问题
* fix 修复 minio 无 perfix 问题
* 发布 v3.0.0
* update 降级 minio 依赖版本
* update service 统一使用 ServicePlusImpl
2021-08-20 08:52:13 +00:00
879f18f6f0 update 优化 OSS 模块与上传组件 异常处理 2021-08-18 19:19:12 +08:00
12e69e946e fix 修复 OSS配置清空被过滤问题 2021-08-18 18:25:17 +08:00
d4758aae1e fix 修复 新版本说明 标签错误
(cherry picked from commit 96c4c4da56)
2021-08-18 16:56:04 +08:00
05ca59a525 fix 修复 富文本图片路径错误问题
(cherry picked from commit cf4b49ca3b)
2021-08-18 14:50:31 +08:00
ba018d0d6c fix 修复 minio 无 perfix 问题 2021-08-18 14:15:55 +08:00
c206f938ba 发布 v3.0.0 2021-08-18 11:45:51 +08:00
3294390407 update 降级 minio 依赖版本
(cherry picked from commit a6bde3c5da)
2021-07-30 14:18:13 +08:00
39e3152ed0 update service 统一使用 ServicePlusImpl 2021-07-28 14:43:21 +08:00
2b3ac89fa1 fix 修复 jdk8 与 jdk11 差异问题 2021-07-28 11:57:34 +08:00
3f3a7db544 发布 v2.6.0 2021-07-28 11:32:30 +08:00
a3e781915e fix 修复多数据源druid全局配置缩进错误 引起无效配置问题 2021-07-24 18:24:29 +08:00
dc5c5c292e remove 移除无用配置
(cherry picked from commit aad482a7e0)
2021-07-20 11:15:33 +08:00
fc1864c52e remove 删除无用文档与脚本
(cherry picked from commit 50b7421f28)
2021-07-20 11:14:56 +08:00
8e8520060d 发布 v2.5.2 2021-07-20 11:03:57 +08:00
51d1e3c8c1 发布 v2.5.1 针对 v2.5.0 版本新特性bug修复 2021-07-13 13:57:44 +08:00
49c2809895 Merge remote-tracking branch 'origin/fast' into fast 2021-07-12 11:36:47 +08:00
007a6d0c88 发布 v2.5.0 2021-07-12 11:36:37 +08:00
a77ee34a73 update README.md. 2021-06-25 08:01:35 +00:00
7e3bbb4aab update 更新文档 提问四部曲 2021-06-24 17:13:39 +08:00
17ed4adb90 update 更新文档 提问四部曲 2021-06-24 17:11:14 +08:00
4e93575c94 update 修改readme加入提问四部曲 2021-06-24 17:11:13 +08:00
0e67a487c3 fix 相对路径下载问题 2021-06-24 15:43:46 +08:00
31e4735dcb 发布 v2.4.0 2021-06-24 09:52:40 +08:00
03c459e5a3 同步 dev 分支 2021-06-23 10:02:55 +08:00
3e5b850e25 发布 v2.3.2 2021-06-11 10:00:05 +08:00
801f7cd8f7 发布 2.3.1 2021-06-04 16:20:12 +08:00
d87eb34352 Merge remote-tracking branch 'origin/fast' into fast 2021-06-01 10:53:36 +08:00
59ef30b156 发布 2.3.0 2021-06-01 10:53:30 +08:00
47e2a3e116 fix 修复数据权限编写错误 2021-05-29 21:49:35 +08:00
76aa006db5 update 还原数据权限修改 2021-05-29 19:49:22 +08:00
fab58a4f77 发布 2.2.1 2021-05-29 19:23:45 +08:00
96cdd2490d 同步dev分支 2021-05-26 16:52:24 +08:00
a90a5e9cd9 Merge remote-tracking branch 'origin/fast' into fast
# Conflicts:
#	README.md
2021-05-26 16:51:22 +08:00
08b339b25e 同步dev分支 2021-05-26 16:51:01 +08:00
002c7ffca5 update 更新捐献二维码 2021-05-25 20:45:56 +08:00
a42ef126cd 版本更新 v2.2.0 2021-05-25 14:31:52 +08:00
8a94526110 发版 2.1.2 2021-05-21 18:00:40 +08:00
33c6fdfaa9 发布 v2.1.1 2021-05-18 11:50:29 +08:00
403c12eb9c 版本更新 v2.1.0 2021-05-15 14:45:47 +08:00
687d746b1b 正式发布 v2.0.0 2021-05-14 21:39:30 +08:00
b608002e89 版本更新 v1.0.2 2021-05-13 09:25:56 +08:00
fe8a2b401c 版本更新 v1.0.1 2021-05-11 17:46:48 +08:00
4a4d8f7123 正式发布 1.0.0 2021-05-10 15:32:46 +08:00
92008ff2d7 update 更新作者二维码 2021-05-08 23:56:36 +08:00
3fbf0a8e9e Merge remote-tracking branch 'origin/fast' into fast 2021-05-08 23:37:35 +08:00
0cbcc56cd6 fix 修复数据权限问题 2021-05-08 23:36:50 +08:00
ea7b309211 fix 日志时间sql符号转换问题 2021-05-08 17:07:41 +08:00
d945cb4a30 fix 日志时间sql符号转换问题 2021-05-08 16:56:52 +08:00
ab3e04f3ad update 项目地址项目名 2021-05-06 17:45:27 +08:00
2b5f30b88b fix 部门权限问题 2021-04-28 15:59:04 +08:00
9cb68a350b fix 日志时间问题 2021-04-28 11:52:38 +08:00
14a9df8b7e update 修改MP验证策略 NOT_NULL -> NOT_EMPTY 2021-04-25 10:40:32 +08:00
661325e4c5 同步ruoyi 2021-04-25 09:46:49 +08:00
017faa99c2 update 重写MP注入器 2021-04-25 09:20:39 +08:00
dbe6494b6c update 屏蔽用户密码返回 2021-04-23 16:01:32 +08:00
789dab5138 update 补全实体类 注入注解 2021-04-22 21:11:04 +08:00
e48d5fadc5 add 集成 spring-boot-admin 全方位监控 2021-04-22 15:50:42 +08:00
70492a9715 update mp 化 2021-04-22 10:11:39 +08:00
a3ee939ebb fix feign熔断问题 2021-04-22 09:33:36 +08:00
bd07a69712 fix 代码生成器编辑问题 2021-04-19 19:01:03 +08:00
58d08f0ecf fix Feign 熔断不生效 bug 2021-04-19 17:52:00 +08:00
af07590fd3 Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into fast
 Conflicts:
	pom.xml
	ruoyi-ui/src/assets/styles/ruoyi.scss
	ruoyi-ui/src/components/ThemePicker/index.vue
	ruoyi-ui/src/layout/components/Settings/index.vue
	ruoyi-ui/src/store/modules/settings.js
	ruoyi/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
	ruoyi/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
2021-04-19 17:48:30 +08:00
b36b9ac788 Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into fast
 Conflicts:
	ruoyi/src/main/resources/vm/vue/index-tree.vue.vm
2021-04-16 11:34:02 +08:00
76d49217bb fix 表名上传错误 2021-04-16 11:31:36 +08:00
5b06ff45c5 update 导出 Excel 工作表的名称修改 2021-04-14 14:37:27 +08:00
d4fdcb0894 update 完成所有原生功能使用 Mybatis-Plus 与 Lombok 重写 2021-04-14 13:46:41 +08:00
f28029fade Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into fast
 Conflicts:
	ruoyi-generator/src/main/resources/vm/java/controller.java.vm
	ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
	ruoyi-ui/src/assets/styles/ruoyi.scss
	ruoyi-ui/src/assets/styles/sidebar.scss
	ruoyi-ui/src/layout/components/Navbar.vue
	ruoyi-ui/src/layout/components/Settings/index.vue
	ruoyi-ui/src/layout/components/TagsView/index.vue
	ruoyi-ui/src/settings.js
	ruoyi-ui/src/store/getters.js
	ruoyi-ui/src/store/modules/permission.js
	ruoyi-ui/src/store/modules/settings.js
	ruoyi-ui/src/store/modules/tagsView.js
	ruoyi-ui/src/views/monitor/druid/index.vue
	ruoyi/src/main/resources/application-prod.yml
2021-04-14 13:33:01 +08:00
6aa03ce709 fix bo缺包问题 2021-04-12 10:38:34 +08:00
89f30d9235 update Date参数接收Bo实体格式转换 2021-04-09 11:50:44 +08:00
e8bb56938e Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into fast
 Conflicts:
	ruoyi-ui/src/assets/styles/ruoyi.scss
	ruoyi-ui/src/utils/zipdownload.js
	ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
	ruoyi/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
	ruoyi/src/main/resources/mapper/system/SysRoleMapper.xml
	ruoyi/src/main/resources/mapper/system/SysUserMapper.xml
2021-04-08 17:19:25 +08:00
43d7949246 fix 字节转换 bug 2021-04-08 16:42:03 +08:00
307c4984a9 update 默认增加editBo主键生成 2021-04-08 16:30:28 +08:00
fb6290e481 fix controller 接口路径问题 2021-04-04 20:02:42 +08:00
24be6a0b7a fix 代码生成器问题 2021-04-04 11:29:40 +08:00
bbc8a2c062 fix 父类少包问题 2021-04-04 11:29:20 +08:00
aaa6b7ed3c fix remove 方法类型错误 2021-04-03 17:01:23 +08:00
a4448fef0a fix Page 路径导入 2021-04-02 23:07:57 +08:00
4ef331cf80 add 添加多模块分支 2021-04-02 16:15:29 +08:00
b8806360f8 add 添加单模块分支 2021-04-02 16:13:31 +08:00
fad9a8a168 add 添加单模块分支 2021-04-02 16:12:58 +08:00
2ba304819d init 单模块项目 2021-04-02 15:59:05 +08:00
444 changed files with 2450 additions and 2814 deletions

66
pom.xml
View File

@ -265,76 +265,12 @@
<version>${bouncycastle.version}</version> <version>${bouncycastle.version}</version>
</dependency> </dependency>
<!-- 定时任务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-job</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- OSS对象存储模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oss</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- SMS短信模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-sms</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- demo模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-demo</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<modules> <modules>
<module>ruoyi-admin</module> <module>ruoyi</module>
<module>ruoyi-framework</module>
<module>ruoyi-system</module>
<module>ruoyi-job</module>
<module>ruoyi-generator</module>
<module>ruoyi-common</module>
<module>ruoyi-demo</module>
<module>ruoyi-extend</module> <module>ruoyi-extend</module>
<module>ruoyi-oss</module>
<module>ruoyi-sms</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>

View File

@ -1,131 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>ruoyi-admin</artifactId>
<description>
web服务入口
</description>
<dependencies>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- Oracle -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
</dependency>
<!-- PostgreSql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- SqlServer -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-job</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oss</artifactId>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
</dependency>
<!-- demo模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-demo</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- skywalking 整合 logback -->
<!-- <dependency>-->
<!-- <groupId>org.apache.skywalking</groupId>-->
<!-- <artifactId>apm-toolkit-logback-1.x</artifactId>-->
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.skywalking</groupId>-->
<!-- <artifactId>apm-toolkit-trace</artifactId>-->
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,170 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common</artifactId>
<description>
common通用工具
</description>
<dependencies>
<!-- Spring框架基本的核心工具 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- SpringWeb模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
</dependency>
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- JSON工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<!-- yml解析器 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<!-- servlet包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- dynamic-datasource 多数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-jwt</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-javadoc</artifactId>
</dependency>
<!-- 自动生成YML配置关联JSON文件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-27</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
</dependency>
<!-- 加密包引入 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
</dependency>
<!-- 离线IP地址定位库 -->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-demo</artifactId>
<description>
demo模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-sms</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,72 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-framework</artifactId>
<description>
framework框架核心
</description>
<dependencies>
<!-- SpringBoot Web容器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- web 容器使用 undertow 性能更强 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- SpringBoot 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- sql性能分析插件 -->
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-generator</artifactId>
<description>
generator代码生成
</description>
<dependencies>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,3 +0,0 @@
java包使用 `.` 分割 resource 目录使用 `/` 分割
<br>
此文件目的 防止文件夹粘连找不到 `xml` 文件

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>ruoyi-job</artifactId>
<description>
任务调度
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-oss</artifactId>
<description>
OSS对象存储模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-sms</artifactId>
<description>
SMS短信模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>org.dromara.sms4j</groupId>
<artifactId>sms4j-spring-boot-starter</artifactId>
<exclusions>
<!-- 排除京东短信内存在的fastjson等待作者后续修复 -->
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-system</artifactId>
<description>
system系统模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<!-- OSS功能模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oss</artifactId>
</dependency>
<!-- SMS功能模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-sms</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,3 +0,0 @@
java包使用 `.` 分割 resource 目录使用 `/` 分割
<br>
此文件目的 防止文件夹粘连找不到 `xml` 文件

File diff suppressed because one or more lines are too long

View File

@ -1,57 +1,57 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询缓存详细 // 查询缓存详细
export function getCache() { export function getCache() {
return request({ return request({
url: '/monitor/cache', url: '/monitor/cache',
method: 'get' method: 'get'
}) })
} }
// 查询缓存名称列表 // 查询缓存名称列表
export function listCacheName() { export function listCacheName() {
return request({ return request({
url: '/monitor/cache/getNames', url: '/monitor/cache/getNames',
method: 'get' method: 'get'
}) })
} }
// 查询缓存键名列表 // 查询缓存键名列表
export function listCacheKey(cacheName) { export function listCacheKey(cacheName) {
return request({ return request({
url: '/monitor/cache/getKeys/' + cacheName, url: '/monitor/cache/getKeys/' + cacheName,
method: 'get' method: 'get'
}) })
} }
// 查询缓存内容 // 查询缓存内容
export function getCacheValue(cacheName, cacheKey) { export function getCacheValue(cacheName, cacheKey) {
return request({ return request({
url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey, url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
method: 'get' method: 'get'
}) })
} }
// 清理指定名称缓存 // 清理指定名称缓存
export function clearCacheName(cacheName) { export function clearCacheName(cacheName) {
return request({ return request({
url: '/monitor/cache/clearCacheName/' + cacheName, url: '/monitor/cache/clearCacheName/' + cacheName,
method: 'delete' method: 'delete'
}) })
} }
// 清理指定键名缓存 // 清理指定键名缓存
export function clearCacheKey(cacheName, cacheKey) { export function clearCacheKey(cacheName, cacheKey) {
return request({ return request({
url: '/monitor/cache/clearCacheKey/'+ cacheName + "/" + cacheKey, url: '/monitor/cache/clearCacheKey/'+ cacheName + "/" + cacheKey,
method: 'delete' method: 'delete'
}) })
} }
// 清理全部缓存 // 清理全部缓存
export function clearCacheAll() { export function clearCacheAll() {
return request({ return request({
url: '/monitor/cache/clearCacheAll', url: '/monitor/cache/clearCacheAll',
method: 'delete' method: 'delete'
}) })
} }

View File

@ -1,116 +1,116 @@
<template> <template>
<el-form size="small"> <el-form size="small">
<el-form-item> <el-form-item>
<el-radio v-model='radioValue' :label="1"> <el-radio v-model='radioValue' :label="1">
分钟允许的通配符[, - * /] 分钟允许的通配符[, - * /]
</el-radio> </el-radio>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-radio v-model='radioValue' :label="2"> <el-radio v-model='radioValue' :label="2">
周期从 周期从
<el-input-number v-model='cycle01' :min="0" :max="58" /> - <el-input-number v-model='cycle01' :min="0" :max="58" /> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 分钟 <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 分钟
</el-radio> </el-radio>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-radio v-model='radioValue' :label="3"> <el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始 <el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始
<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 分钟执行一次 <el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 分钟执行一次
</el-radio> </el-radio>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-radio v-model='radioValue' :label="4"> <el-radio v-model='radioValue' :label="4">
指定 指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%"> <el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option> <el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
</el-select> </el-select>
</el-radio> </el-radio>
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
radioValue: 1, radioValue: 1,
cycle01: 1, cycle01: 1,
cycle02: 2, cycle02: 2,
average01: 0, average01: 0,
average02: 1, average02: 1,
checkboxList: [], checkboxList: [],
checkNum: this.$options.propsData.check checkNum: this.$options.propsData.check
} }
}, },
name: 'crontab-min', name: 'crontab-min',
props: ['check', 'cron'], props: ['check', 'cron'],
methods: { methods: {
// 单选按钮值变化时 // 单选按钮值变化时
radioChange() { radioChange() {
switch (this.radioValue) { switch (this.radioValue) {
case 1: case 1:
this.$emit('update', 'min', '*', 'min'); this.$emit('update', 'min', '*', 'min');
break; break;
case 2: case 2:
this.$emit('update', 'min', this.cycleTotal, 'min'); this.$emit('update', 'min', this.cycleTotal, 'min');
break; break;
case 3: case 3:
this.$emit('update', 'min', this.averageTotal, 'min'); this.$emit('update', 'min', this.averageTotal, 'min');
break; break;
case 4: case 4:
this.$emit('update', 'min', this.checkboxString, 'min'); this.$emit('update', 'min', this.checkboxString, 'min');
break; break;
} }
}, },
// 周期两个值变化时 // 周期两个值变化时
cycleChange() { cycleChange() {
if (this.radioValue == '2') { if (this.radioValue == '2') {
this.$emit('update', 'min', this.cycleTotal, 'min'); this.$emit('update', 'min', this.cycleTotal, 'min');
} }
}, },
// 平均两个值变化时 // 平均两个值变化时
averageChange() { averageChange() {
if (this.radioValue == '3') { if (this.radioValue == '3') {
this.$emit('update', 'min', this.averageTotal, 'min'); this.$emit('update', 'min', this.averageTotal, 'min');
} }
}, },
// checkbox值变化时 // checkbox值变化时
checkboxChange() { checkboxChange() {
if (this.radioValue == '4') { if (this.radioValue == '4') {
this.$emit('update', 'min', this.checkboxString, 'min'); this.$emit('update', 'min', this.checkboxString, 'min');
} }
}, },
}, },
watch: { watch: {
'radioValue': 'radioChange', 'radioValue': 'radioChange',
'cycleTotal': 'cycleChange', 'cycleTotal': 'cycleChange',
'averageTotal': 'averageChange', 'averageTotal': 'averageChange',
'checkboxString': 'checkboxChange', 'checkboxString': 'checkboxChange',
}, },
computed: { computed: {
// 计算两个周期值 // 计算两个周期值
cycleTotal: function () { cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 0, 58) const cycle01 = this.checkNum(this.cycle01, 0, 58)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59) const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
return cycle01 + '-' + cycle02; return cycle01 + '-' + cycle02;
}, },
// 计算平均用到的值 // 计算平均用到的值
averageTotal: function () { averageTotal: function () {
const average01 = this.checkNum(this.average01, 0, 58) const average01 = this.checkNum(this.average01, 0, 58)
const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0) const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
return average01 + '/' + average02; return average01 + '/' + average02;
}, },
// 计算勾选的checkbox值合集 // 计算勾选的checkbox值合集
checkboxString: function () { checkboxString: function () {
let str = this.checkboxList.join(); let str = this.checkboxList.join();
return str == '' ? '*' : str; return str == '' ? '*' : str;
} }
} }
} }
</script> </script>

View File

@ -1,49 +1,49 @@
import Vue from 'vue' import Vue from 'vue'
import store from '@/store' import store from '@/store'
import DataDict from '@/utils/dict' import DataDict from '@/utils/dict'
import { getDicts as getDicts } from '@/api/system/dict/data' import { getDicts as getDicts } from '@/api/system/dict/data'
function searchDictByKey(dict, key) { function searchDictByKey(dict, key) {
if (key == null && key == "") { if (key == null && key == "") {
return null return null
} }
try { try {
for (let i = 0; i < dict.length; i++) { for (let i = 0; i < dict.length; i++) {
if (dict[i].key == key) { if (dict[i].key == key) {
return dict[i].value return dict[i].value
} }
} }
} catch (e) { } catch (e) {
return null return null
} }
} }
function install() { function install() {
Vue.use(DataDict, { Vue.use(DataDict, {
metas: { metas: {
'*': { '*': {
labelField: 'dictLabel', labelField: 'dictLabel',
valueField: 'dictValue', valueField: 'dictValue',
request(dictMeta) { request(dictMeta) {
const storeDict = searchDictByKey(store.getters.dict, dictMeta.type) const storeDict = searchDictByKey(store.getters.dict, dictMeta.type)
if (storeDict) { if (storeDict) {
return new Promise(resolve => { resolve(storeDict) }) return new Promise(resolve => { resolve(storeDict) })
} else { } else {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
getDicts(dictMeta.type).then(res => { getDicts(dictMeta.type).then(res => {
store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data }) store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data })
resolve(res.data) resolve(res.data)
}).catch(error => { }).catch(error => {
reject(error) reject(error)
}) })
}) })
} }
}, },
}, },
}, },
}) })
} }
export default { export default {
install, install,
} }

View File

@ -1,36 +1,36 @@
<template> <template>
<div v-loading="loading" :style="'height:' + height"> <div v-loading="loading" :style="'height:' + height">
<iframe <iframe
:src="src" :src="src"
frameborder="no" frameborder="no"
style="width: 100%; height: 100%" style="width: 100%; height: 100%"
scrolling="auto" scrolling="auto"
/> />
</div> </div>
</template> </template>
<script> <script>
export default { export default {
props: { props: {
src: { src: {
type: String, type: String,
required: true required: true
}, },
}, },
data() { data() {
return { return {
height: document.documentElement.clientHeight - 94.5 + "px;", height: document.documentElement.clientHeight - 94.5 + "px;",
loading: true, loading: true,
url: this.src url: this.src
}; };
}, },
mounted: function () { mounted: function () {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
}, 300); }, 300);
const that = this; const that = this;
window.onresize = function temp() { window.onresize = function temp() {
that.height = document.documentElement.clientHeight - 94.5 + "px;"; that.height = document.documentElement.clientHeight - 94.5 + "px;";
}; };
} }
}; };
</script> </script>

View File

@ -1,64 +1,64 @@
/** /**
* v-dialogDrag 弹窗拖拽 * v-dialogDrag 弹窗拖拽
* Copyright (c) 2019 ruoyi * Copyright (c) 2019 ruoyi
*/ */
export default { export default {
bind(el, binding, vnode, oldVnode) { bind(el, binding, vnode, oldVnode) {
const value = binding.value const value = binding.value
if (value == false) return if (value == false) return
// 获取拖拽内容头部 // 获取拖拽内容头部
const dialogHeaderEl = el.querySelector('.el-dialog__header'); const dialogHeaderEl = el.querySelector('.el-dialog__header');
const dragDom = el.querySelector('.el-dialog'); const dragDom = el.querySelector('.el-dialog');
dialogHeaderEl.style.cursor = 'move'; dialogHeaderEl.style.cursor = 'move';
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null); // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null); const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
dragDom.style.position = 'absolute'; dragDom.style.position = 'absolute';
dragDom.style.marginTop = 0; dragDom.style.marginTop = 0;
let width = dragDom.style.width; let width = dragDom.style.width;
if (width.includes('%')) { if (width.includes('%')) {
width = +document.body.clientWidth * (+width.replace(/\%/g, '') / 100); width = +document.body.clientWidth * (+width.replace(/\%/g, '') / 100);
} else { } else {
width = +width.replace(/\px/g, ''); width = +width.replace(/\px/g, '');
} }
dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`; dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`;
// 鼠标按下事件 // 鼠标按下事件
dialogHeaderEl.onmousedown = (e) => { dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离 (鼠标点击位置距离可视窗口的距离) // 鼠标按下,计算当前元素距离可视区的距离 (鼠标点击位置距离可视窗口的距离)
const disX = e.clientX - dialogHeaderEl.offsetLeft; const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop; const disY = e.clientY - dialogHeaderEl.offsetTop;
// 获取到的值带px 正则匹配替换 // 获取到的值带px 正则匹配替换
let styL, styT; let styL, styT;
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (sty.left.includes('%')) { if (sty.left.includes('%')) {
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100); styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100); styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
} else { } else {
styL = +sty.left.replace(/\px/g, ''); styL = +sty.left.replace(/\px/g, '');
styT = +sty.top.replace(/\px/g, ''); styT = +sty.top.replace(/\px/g, '');
}; };
// 鼠标拖拽事件 // 鼠标拖拽事件
document.onmousemove = function (e) { document.onmousemove = function (e) {
// 通过事件委托,计算移动的距离 (开始拖拽至结束拖拽的距离) // 通过事件委托,计算移动的距离 (开始拖拽至结束拖拽的距离)
const l = e.clientX - disX; const l = e.clientX - disX;
const t = e.clientY - disY; const t = e.clientY - disY;
let finallyL = l + styL let finallyL = l + styL
let finallyT = t + styT let finallyT = t + styT
// 移动当前元素 // 移动当前元素
dragDom.style.left = `${finallyL}px`; dragDom.style.left = `${finallyL}px`;
dragDom.style.top = `${finallyT}px`; dragDom.style.top = `${finallyT}px`;
}; };
document.onmouseup = function (e) { document.onmouseup = function (e) {
document.onmousemove = null; document.onmousemove = null;
document.onmouseup = null; document.onmouseup = null;
}; };
} }
} }
}; };

View File

@ -1,34 +1,34 @@
/** /**
* v-dialogDragWidth 可拖动弹窗高度(右下角) * v-dialogDragWidth 可拖动弹窗高度(右下角)
* Copyright (c) 2019 ruoyi * Copyright (c) 2019 ruoyi
*/ */
export default { export default {
bind(el) { bind(el) {
const dragDom = el.querySelector('.el-dialog'); const dragDom = el.querySelector('.el-dialog');
const lineEl = document.createElement('div'); const lineEl = document.createElement('div');
lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;'; lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;';
lineEl.addEventListener('mousedown', lineEl.addEventListener('mousedown',
function(e) { function(e) {
// 鼠标按下,计算当前元素距离可视区的距离 // 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - el.offsetLeft; const disX = e.clientX - el.offsetLeft;
const disY = e.clientY - el.offsetTop; const disY = e.clientY - el.offsetTop;
// 当前宽度 高度 // 当前宽度 高度
const curWidth = dragDom.offsetWidth; const curWidth = dragDom.offsetWidth;
const curHeight = dragDom.offsetHeight; const curHeight = dragDom.offsetHeight;
document.onmousemove = function(e) { document.onmousemove = function(e) {
e.preventDefault(); // 移动时禁用默认事件 e.preventDefault(); // 移动时禁用默认事件
// 通过事件委托,计算移动的距离 // 通过事件委托,计算移动的距离
const xl = e.clientX - disX; const xl = e.clientX - disX;
const yl = e.clientY - disY const yl = e.clientY - disY
dragDom.style.width = `${curWidth + xl}px`; dragDom.style.width = `${curWidth + xl}px`;
dragDom.style.height = `${curHeight + yl}px`; dragDom.style.height = `${curHeight + yl}px`;
}; };
document.onmouseup = function(e) { document.onmouseup = function(e) {
document.onmousemove = null; document.onmousemove = null;
document.onmouseup = null; document.onmouseup = null;
}; };
}, false); }, false);
dragDom.appendChild(lineEl); dragDom.appendChild(lineEl);
} }
} }

View File

@ -1,30 +1,30 @@
/** /**
* v-dialogDragWidth 可拖动弹窗宽度(右侧边) * v-dialogDragWidth 可拖动弹窗宽度(右侧边)
* Copyright (c) 2019 ruoyi * Copyright (c) 2019 ruoyi
*/ */
export default { export default {
bind(el) { bind(el) {
const dragDom = el.querySelector('.el-dialog'); const dragDom = el.querySelector('.el-dialog');
const lineEl = document.createElement('div'); const lineEl = document.createElement('div');
lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;'; lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;';
lineEl.addEventListener('mousedown', lineEl.addEventListener('mousedown',
function (e) { function (e) {
// 鼠标按下,计算当前元素距离可视区的距离 // 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - el.offsetLeft; const disX = e.clientX - el.offsetLeft;
// 当前宽度 // 当前宽度
const curWidth = dragDom.offsetWidth; const curWidth = dragDom.offsetWidth;
document.onmousemove = function (e) { document.onmousemove = function (e) {
e.preventDefault(); // 移动时禁用默认事件 e.preventDefault(); // 移动时禁用默认事件
// 通过事件委托,计算移动的距离 // 通过事件委托,计算移动的距离
const l = e.clientX - disX; const l = e.clientX - disX;
dragDom.style.width = `${curWidth + l}px`; dragDom.style.width = `${curWidth + l}px`;
}; };
document.onmouseup = function (e) { document.onmouseup = function (e) {
document.onmousemove = null; document.onmousemove = null;
document.onmouseup = null; document.onmouseup = null;
}; };
}, false); }, false);
dragDom.appendChild(lineEl); dragDom.appendChild(lineEl);
} }
} }

View File

@ -1,47 +1,47 @@
<template> <template>
<div :style="'height:' + height" v-loading="loading" element-loading-text="正在加载页面,请稍候!"> <div :style="'height:' + height" v-loading="loading" element-loading-text="正在加载页面,请稍候!">
<iframe <iframe
:id="iframeId" :id="iframeId"
style="width: 100%; height: 100%" style="width: 100%; height: 100%"
:src="src" :src="src"
frameborder="no" frameborder="no"
></iframe> ></iframe>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
props: { props: {
src: { src: {
type: String, type: String,
default: "/" default: "/"
}, },
iframeId: { iframeId: {
type: String type: String
} }
}, },
data() { data() {
return { return {
loading: false, loading: false,
height: document.documentElement.clientHeight - 94.5 + "px;" height: document.documentElement.clientHeight - 94.5 + "px;"
}; };
}, },
mounted() { mounted() {
var _this = this; var _this = this;
const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/"); const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/");
const iframe = document.querySelector(iframeId); const iframe = document.querySelector(iframeId);
// iframe页面loading控制 // iframe页面loading控制
if (iframe.attachEvent) { if (iframe.attachEvent) {
this.loading = true; this.loading = true;
iframe.attachEvent("onload", function () { iframe.attachEvent("onload", function () {
_this.loading = false; _this.loading = false;
}); });
} else { } else {
this.loading = true; this.loading = true;
iframe.onload = function () { iframe.onload = function () {
_this.loading = false; _this.loading = false;
}; };
} }
} }
}; };
</script> </script>

View File

@ -1,60 +1,60 @@
import store from '@/store' import store from '@/store'
function authPermission(permission) { function authPermission(permission) {
const all_permission = "*:*:*"; const all_permission = "*:*:*";
const permissions = store.getters && store.getters.permissions const permissions = store.getters && store.getters.permissions
if (permission && permission.length > 0) { if (permission && permission.length > 0) {
return permissions.some(v => { return permissions.some(v => {
return all_permission === v || v === permission return all_permission === v || v === permission
}) })
} else { } else {
return false return false
} }
} }
function authRole(role) { function authRole(role) {
const super_admin = "admin"; const super_admin = "admin";
const roles = store.getters && store.getters.roles const roles = store.getters && store.getters.roles
if (role && role.length > 0) { if (role && role.length > 0) {
return roles.some(v => { return roles.some(v => {
return super_admin === v || v === role return super_admin === v || v === role
}) })
} else { } else {
return false return false
} }
} }
export default { export default {
// 验证用户是否具备某权限 // 验证用户是否具备某权限
hasPermi(permission) { hasPermi(permission) {
return authPermission(permission); return authPermission(permission);
}, },
// 验证用户是否含有指定权限,只需包含其中一个 // 验证用户是否含有指定权限,只需包含其中一个
hasPermiOr(permissions) { hasPermiOr(permissions) {
return permissions.some(item => { return permissions.some(item => {
return authPermission(item) return authPermission(item)
}) })
}, },
// 验证用户是否含有指定权限,必须全部拥有 // 验证用户是否含有指定权限,必须全部拥有
hasPermiAnd(permissions) { hasPermiAnd(permissions) {
return permissions.every(item => { return permissions.every(item => {
return authPermission(item) return authPermission(item)
}) })
}, },
// 验证用户是否具备某角色 // 验证用户是否具备某角色
hasRole(role) { hasRole(role) {
return authRole(role); return authRole(role);
}, },
// 验证用户是否含有指定角色,只需包含其中一个 // 验证用户是否含有指定角色,只需包含其中一个
hasRoleOr(roles) { hasRoleOr(roles) {
return roles.some(item => { return roles.some(item => {
return authRole(item) return authRole(item)
}) })
}, },
// 验证用户是否含有指定角色,必须全部拥有 // 验证用户是否含有指定角色,必须全部拥有
hasRoleAnd(roles) { hasRoleAnd(roles) {
return roles.every(item => { return roles.every(item => {
return authRole(item) return authRole(item)
}) })
} }
} }

View File

@ -1,77 +1,77 @@
const sessionCache = { const sessionCache = {
set (key, value) { set (key, value) {
if (!sessionStorage) { if (!sessionStorage) {
return return
} }
if (key != null && value != null) { if (key != null && value != null) {
sessionStorage.setItem(key, value) sessionStorage.setItem(key, value)
} }
}, },
get (key) { get (key) {
if (!sessionStorage) { if (!sessionStorage) {
return null return null
} }
if (key == null) { if (key == null) {
return null return null
} }
return sessionStorage.getItem(key) return sessionStorage.getItem(key)
}, },
setJSON (key, jsonValue) { setJSON (key, jsonValue) {
if (jsonValue != null) { if (jsonValue != null) {
this.set(key, JSON.stringify(jsonValue)) this.set(key, JSON.stringify(jsonValue))
} }
}, },
getJSON (key) { getJSON (key) {
const value = this.get(key) const value = this.get(key)
if (value != null) { if (value != null) {
return JSON.parse(value) return JSON.parse(value)
} }
}, },
remove (key) { remove (key) {
sessionStorage.removeItem(key); sessionStorage.removeItem(key);
} }
} }
const localCache = { const localCache = {
set (key, value) { set (key, value) {
if (!localStorage) { if (!localStorage) {
return return
} }
if (key != null && value != null) { if (key != null && value != null) {
localStorage.setItem(key, value) localStorage.setItem(key, value)
} }
}, },
get (key) { get (key) {
if (!localStorage) { if (!localStorage) {
return null return null
} }
if (key == null) { if (key == null) {
return null return null
} }
return localStorage.getItem(key) return localStorage.getItem(key)
}, },
setJSON (key, jsonValue) { setJSON (key, jsonValue) {
if (jsonValue != null) { if (jsonValue != null) {
this.set(key, JSON.stringify(jsonValue)) this.set(key, JSON.stringify(jsonValue))
} }
}, },
getJSON (key) { getJSON (key) {
const value = this.get(key) const value = this.get(key)
if (value != null) { if (value != null) {
return JSON.parse(value) return JSON.parse(value)
} }
}, },
remove (key) { remove (key) {
localStorage.removeItem(key); localStorage.removeItem(key);
} }
} }
export default { export default {
/** /**
* 会话级缓存 * 会话级缓存
*/ */
session: sessionCache, session: sessionCache,
/** /**
* 本地缓存 * 本地缓存
*/ */
local: localCache local: localCache
} }

View File

@ -1,20 +1,20 @@
import tab from './tab' import tab from './tab'
import auth from './auth' import auth from './auth'
import cache from './cache' import cache from './cache'
import modal from './modal' import modal from './modal'
import download from './download' import download from './download'
export default { export default {
install(Vue) { install(Vue) {
// 页签操作 // 页签操作
Vue.prototype.$tab = tab Vue.prototype.$tab = tab
// 认证对象 // 认证对象
Vue.prototype.$auth = auth Vue.prototype.$auth = auth
// 缓存对象 // 缓存对象
Vue.prototype.$cache = cache Vue.prototype.$cache = cache
// 模态框对象 // 模态框对象
Vue.prototype.$modal = modal Vue.prototype.$modal = modal
// 下载文件 // 下载文件
Vue.prototype.$download = download Vue.prototype.$download = download
} }
} }

View File

@ -1,83 +1,83 @@
import { Message, MessageBox, Notification, Loading } from 'element-ui' import { Message, MessageBox, Notification, Loading } from 'element-ui'
let loadingInstance; let loadingInstance;
export default { export default {
// 消息提示 // 消息提示
msg(content) { msg(content) {
Message.info(content) Message.info(content)
}, },
// 错误消息 // 错误消息
msgError(content) { msgError(content) {
Message.error(content) Message.error(content)
}, },
// 成功消息 // 成功消息
msgSuccess(content) { msgSuccess(content) {
Message.success(content) Message.success(content)
}, },
// 警告消息 // 警告消息
msgWarning(content) { msgWarning(content) {
Message.warning(content) Message.warning(content)
}, },
// 弹出提示 // 弹出提示
alert(content) { alert(content) {
MessageBox.alert(content, "系统提示") MessageBox.alert(content, "系统提示")
}, },
// 错误提示 // 错误提示
alertError(content) { alertError(content) {
MessageBox.alert(content, "系统提示", { type: 'error' }) MessageBox.alert(content, "系统提示", { type: 'error' })
}, },
// 成功提示 // 成功提示
alertSuccess(content) { alertSuccess(content) {
MessageBox.alert(content, "系统提示", { type: 'success' }) MessageBox.alert(content, "系统提示", { type: 'success' })
}, },
// 警告提示 // 警告提示
alertWarning(content) { alertWarning(content) {
MessageBox.alert(content, "系统提示", { type: 'warning' }) MessageBox.alert(content, "系统提示", { type: 'warning' })
}, },
// 通知提示 // 通知提示
notify(content) { notify(content) {
Notification.info(content) Notification.info(content)
}, },
// 错误通知 // 错误通知
notifyError(content) { notifyError(content) {
Notification.error(content); Notification.error(content);
}, },
// 成功通知 // 成功通知
notifySuccess(content) { notifySuccess(content) {
Notification.success(content) Notification.success(content)
}, },
// 警告通知 // 警告通知
notifyWarning(content) { notifyWarning(content) {
Notification.warning(content) Notification.warning(content)
}, },
// 确认窗体 // 确认窗体
confirm(content) { confirm(content) {
return MessageBox.confirm(content, "系统提示", { return MessageBox.confirm(content, "系统提示", {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: "warning", type: "warning",
}) })
}, },
// 提交内容 // 提交内容
prompt(content) { prompt(content) {
return MessageBox.prompt(content, "系统提示", { return MessageBox.prompt(content, "系统提示", {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: "warning", type: "warning",
}) })
}, },
// 打开遮罩层 // 打开遮罩层
loading(content) { loading(content) {
loadingInstance = Loading.service({ loadingInstance = Loading.service({
lock: true, lock: true,
text: content, text: content,
spinner: "el-icon-loading", spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)", background: "rgba(0, 0, 0, 0.7)",
}) })
}, },
// 关闭遮罩层 // 关闭遮罩层
closeLoading() { closeLoading() {
loadingInstance.close(); loadingInstance.close();
} }
} }

View File

@ -1,50 +1,50 @@
const state = { const state = {
dict: new Array() dict: new Array()
} }
const mutations = { const mutations = {
SET_DICT: (state, { key, value }) => { SET_DICT: (state, { key, value }) => {
if (key !== null && key !== "") { if (key !== null && key !== "") {
state.dict.push({ state.dict.push({
key: key, key: key,
value: value value: value
}) })
} }
}, },
REMOVE_DICT: (state, key) => { REMOVE_DICT: (state, key) => {
try { try {
for (let i = 0; i < state.dict.length; i++) { for (let i = 0; i < state.dict.length; i++) {
if (state.dict[i].key == key) { if (state.dict[i].key == key) {
state.dict.splice(i, 1) state.dict.splice(i, 1)
return true return true
} }
} }
} catch (e) { } catch (e) {
} }
}, },
CLEAN_DICT: (state) => { CLEAN_DICT: (state) => {
state.dict = new Array() state.dict = new Array()
} }
} }
const actions = { const actions = {
// 设置字典 // 设置字典
setDict({ commit }, data) { setDict({ commit }, data) {
commit('SET_DICT', data) commit('SET_DICT', data)
}, },
// 删除字典 // 删除字典
removeDict({ commit }, key) { removeDict({ commit }, key) {
commit('REMOVE_DICT', key) commit('REMOVE_DICT', key)
}, },
// 清空字典 // 清空字典
cleanDict({ commit }) { cleanDict({ commit }) {
commit('CLEAN_DICT') commit('CLEAN_DICT')
} }
} }
export default { export default {
namespaced: true, namespaced: true,
state, state,
mutations, mutations,
actions actions
} }

View File

@ -1,82 +1,82 @@
import Vue from 'vue' import Vue from 'vue'
import { mergeRecursive } from "@/utils/ruoyi"; import { mergeRecursive } from "@/utils/ruoyi";
import DictMeta from './DictMeta' import DictMeta from './DictMeta'
import DictData from './DictData' import DictData from './DictData'
const DEFAULT_DICT_OPTIONS = { const DEFAULT_DICT_OPTIONS = {
types: [], types: [],
} }
/** /**
* @classdesc 字典 * @classdesc 字典
* @property {Object} label 标签对象,内部属性名为字典类型名称 * @property {Object} label 标签对象,内部属性名为字典类型名称
* @property {Object} dict 字段数组,内部属性名为字典类型名称 * @property {Object} dict 字段数组,内部属性名为字典类型名称
* @property {Array.<DictMeta>} _dictMetas 字典元数据数组 * @property {Array.<DictMeta>} _dictMetas 字典元数据数组
*/ */
export default class Dict { export default class Dict {
constructor() { constructor() {
this.owner = null this.owner = null
this.label = {} this.label = {}
this.type = {} this.type = {}
} }
init(options) { init(options) {
if (options instanceof Array) { if (options instanceof Array) {
options = { types: options } options = { types: options }
} }
const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options) const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
if (opts.types === undefined) { if (opts.types === undefined) {
throw new Error('need dict types') throw new Error('need dict types')
} }
const ps = [] const ps = []
this._dictMetas = opts.types.map(t => DictMeta.parse(t)) this._dictMetas = opts.types.map(t => DictMeta.parse(t))
this._dictMetas.forEach(dictMeta => { this._dictMetas.forEach(dictMeta => {
const type = dictMeta.type const type = dictMeta.type
Vue.set(this.label, type, {}) Vue.set(this.label, type, {})
Vue.set(this.type, type, []) Vue.set(this.type, type, [])
if (dictMeta.lazy) { if (dictMeta.lazy) {
return return
} }
ps.push(loadDict(this, dictMeta)) ps.push(loadDict(this, dictMeta))
}) })
return Promise.all(ps) return Promise.all(ps)
} }
/** /**
* 重新加载字典 * 重新加载字典
* @param {String} type 字典类型 * @param {String} type 字典类型
*/ */
reloadDict(type) { reloadDict(type) {
const dictMeta = this._dictMetas.find(e => e.type === type) const dictMeta = this._dictMetas.find(e => e.type === type)
if (dictMeta === undefined) { if (dictMeta === undefined) {
return Promise.reject(`the dict meta of ${type} was not found`) return Promise.reject(`the dict meta of ${type} was not found`)
} }
return loadDict(this, dictMeta) return loadDict(this, dictMeta)
} }
} }
/** /**
* 加载字典 * 加载字典
* @param {Dict} dict 字典 * @param {Dict} dict 字典
* @param {DictMeta} dictMeta 字典元数据 * @param {DictMeta} dictMeta 字典元数据
* @returns {Promise} * @returns {Promise}
*/ */
function loadDict(dict, dictMeta) { function loadDict(dict, dictMeta) {
return dictMeta.request(dictMeta) return dictMeta.request(dictMeta)
.then(response => { .then(response => {
const type = dictMeta.type const type = dictMeta.type
let dicts = dictMeta.responseConverter(response, dictMeta) let dicts = dictMeta.responseConverter(response, dictMeta)
if (!(dicts instanceof Array)) { if (!(dicts instanceof Array)) {
console.error('the return of responseConverter must be Array.<DictData>') console.error('the return of responseConverter must be Array.<DictData>')
dicts = [] dicts = []
} else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) { } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
console.error('the type of elements in dicts must be DictData') console.error('the type of elements in dicts must be DictData')
dicts = [] dicts = []
} }
dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts) dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
dicts.forEach(d => { dicts.forEach(d => {
Vue.set(dict.label[type], d.value, d.label) Vue.set(dict.label[type], d.value, d.label)
}) })
return dicts return dicts
}) })
} }

View File

@ -1,17 +1,17 @@
import DictOptions from './DictOptions' import DictOptions from './DictOptions'
import DictData from './DictData' import DictData from './DictData'
export default function(dict, dictMeta) { export default function(dict, dictMeta) {
const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS) const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS)
const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS) const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS)
return new DictData(dict[label], dict[value], dict) return new DictData(dict[label], dict[value], dict)
} }
/** /**
* 确定字典字段 * 确定字典字段
* @param {DictData} dict * @param {DictData} dict
* @param {...String} fields * @param {...String} fields
*/ */
function determineDictField(dict, ...fields) { function determineDictField(dict, ...fields) {
return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f)) return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f))
} }

View File

@ -1,13 +1,13 @@
/** /**
* @classdesc 字典数据 * @classdesc 字典数据
* @property {String} label 标签 * @property {String} label 标签
* @property {*} value 标签 * @property {*} value 标签
* @property {Object} raw 原始数据 * @property {Object} raw 原始数据
*/ */
export default class DictData { export default class DictData {
constructor(label, value, raw) { constructor(label, value, raw) {
this.label = label this.label = label
this.value = value this.value = value
this.raw = raw this.raw = raw
} }
} }

View File

@ -1,38 +1,38 @@
import { mergeRecursive } from "@/utils/ruoyi"; import { mergeRecursive } from "@/utils/ruoyi";
import DictOptions from './DictOptions' import DictOptions from './DictOptions'
/** /**
* @classdesc 字典元数据 * @classdesc 字典元数据
* @property {String} type 类型 * @property {String} type 类型
* @property {Function} request 请求 * @property {Function} request 请求
* @property {String} label 标签字段 * @property {String} label 标签字段
* @property {String} value 值字段 * @property {String} value 值字段
*/ */
export default class DictMeta { export default class DictMeta {
constructor(options) { constructor(options) {
this.type = options.type this.type = options.type
this.request = options.request this.request = options.request
this.responseConverter = options.responseConverter this.responseConverter = options.responseConverter
this.labelField = options.labelField this.labelField = options.labelField
this.valueField = options.valueField this.valueField = options.valueField
this.lazy = options.lazy === true this.lazy = options.lazy === true
} }
} }
/** /**
* 解析字典元数据 * 解析字典元数据
* @param {Object} options * @param {Object} options
* @returns {DictMeta} * @returns {DictMeta}
*/ */
DictMeta.parse= function(options) { DictMeta.parse= function(options) {
let opts = null let opts = null
if (typeof options === 'string') { if (typeof options === 'string') {
opts = DictOptions.metas[options] || {} opts = DictOptions.metas[options] || {}
opts.type = options opts.type = options
} else if (typeof options === 'object') { } else if (typeof options === 'object') {
opts = options opts = options
} }
opts = mergeRecursive(DictOptions.metas['*'], opts) opts = mergeRecursive(DictOptions.metas['*'], opts)
return new DictMeta(opts) return new DictMeta(opts)
} }

View File

@ -1,51 +1,51 @@
import { mergeRecursive } from "@/utils/ruoyi"; import { mergeRecursive } from "@/utils/ruoyi";
import dictConverter from './DictConverter' import dictConverter from './DictConverter'
export const options = { export const options = {
metas: { metas: {
'*': { '*': {
/** /**
* 字典请求方法签名为function(dictMeta: DictMeta): Promise * 字典请求方法签名为function(dictMeta: DictMeta): Promise
*/ */
request: (dictMeta) => { request: (dictMeta) => {
console.log(`load dict ${dictMeta.type}`) console.log(`load dict ${dictMeta.type}`)
return Promise.resolve([]) return Promise.resolve([])
}, },
/** /**
* 字典响应数据转换器方法签名为function(response: Object, dictMeta: DictMeta): DictData * 字典响应数据转换器方法签名为function(response: Object, dictMeta: DictMeta): DictData
*/ */
responseConverter, responseConverter,
labelField: 'label', labelField: 'label',
valueField: 'value', valueField: 'value',
}, },
}, },
/** /**
* 默认标签字段 * 默认标签字段
*/ */
DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'], DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'],
/** /**
* 默认值字段 * 默认值字段
*/ */
DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'], DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'],
} }
/** /**
* 映射字典 * 映射字典
* @param {Object} response 字典数据 * @param {Object} response 字典数据
* @param {DictMeta} dictMeta 字典元数据 * @param {DictMeta} dictMeta 字典元数据
* @returns {DictData} * @returns {DictData}
*/ */
function responseConverter(response, dictMeta) { function responseConverter(response, dictMeta) {
const dicts = response.content instanceof Array ? response.content : response const dicts = response.content instanceof Array ? response.content : response
if (dicts === undefined) { if (dicts === undefined) {
console.warn(`no dict data of "${dictMeta.type}" found in the response`) console.warn(`no dict data of "${dictMeta.type}" found in the response`)
return [] return []
} }
return dicts.map(d => dictConverter(d, dictMeta)) return dicts.map(d => dictConverter(d, dictMeta))
} }
export function mergeOptions(src) { export function mergeOptions(src) {
mergeRecursive(options, src) mergeRecursive(options, src)
} }
export default options export default options

View File

@ -1,33 +1,33 @@
import Dict from './Dict' import Dict from './Dict'
import { mergeOptions } from './DictOptions' import { mergeOptions } from './DictOptions'
export default function(Vue, options) { export default function(Vue, options) {
mergeOptions(options) mergeOptions(options)
Vue.mixin({ Vue.mixin({
data() { data() {
if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) { if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) {
return {} return {}
} }
const dict = new Dict() const dict = new Dict()
dict.owner = this dict.owner = this
return { return {
dict dict
} }
}, },
created() { created() {
if (!(this.dict instanceof Dict)) { if (!(this.dict instanceof Dict)) {
return return
} }
options.onCreated && options.onCreated(this.dict) options.onCreated && options.onCreated(this.dict)
this.dict.init(this.$options.dicts).then(() => { this.dict.init(this.$options.dicts).then(() => {
options.onReady && options.onReady(this.dict) options.onReady && options.onReady(this.dict)
this.$nextTick(() => { this.$nextTick(() => {
this.$emit('dictReady', this.dict) this.$emit('dictReady', this.dict)
if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) { if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) {
this.$options.methods.onDictReady.call(this, this.dict) this.$options.methods.onDictReady.call(this, this.dict)
} }
}) })
}) })
}, },
}) })
} }

View File

@ -1,359 +1,359 @@
/* eslint-disable max-len */ /* eslint-disable max-len */
import { trigger } from './config' import { trigger } from './config'
let confGlobal let confGlobal
let someSpanIsNot24 let someSpanIsNot24
export function dialogWrapper(str) { export function dialogWrapper(str) {
return `<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Title"> return `<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Title">
${str} ${str}
<div slot="footer"> <div slot="footer">
<el-button @click="close">取消</el-button> <el-button @click="close">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button> <el-button type="primary" @click="handleConfirm">确定</el-button>
</div> </div>
</el-dialog>` </el-dialog>`
} }
export function vueTemplate(str) { export function vueTemplate(str) {
return `<template> return `<template>
<div> <div>
${str} ${str}
</div> </div>
</template>` </template>`
} }
export function vueScript(str) { export function vueScript(str) {
return `<script> return `<script>
${str} ${str}
</script>` </script>`
} }
export function cssStyle(cssStr) { export function cssStyle(cssStr) {
return `<style> return `<style>
${cssStr} ${cssStr}
</style>` </style>`
} }
function buildFormTemplate(conf, child, type) { function buildFormTemplate(conf, child, type) {
let labelPosition = '' let labelPosition = ''
if (conf.labelPosition !== 'right') { if (conf.labelPosition !== 'right') {
labelPosition = `label-position="${conf.labelPosition}"` labelPosition = `label-position="${conf.labelPosition}"`
} }
const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : '' const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : ''
let str = `<el-form ref="${conf.formRef}" :model="${conf.formModel}" :rules="${conf.formRules}" size="${conf.size}" ${disabled} label-width="${conf.labelWidth}px" ${labelPosition}> let str = `<el-form ref="${conf.formRef}" :model="${conf.formModel}" :rules="${conf.formRules}" size="${conf.size}" ${disabled} label-width="${conf.labelWidth}px" ${labelPosition}>
${child} ${child}
${buildFromBtns(conf, type)} ${buildFromBtns(conf, type)}
</el-form>` </el-form>`
if (someSpanIsNot24) { if (someSpanIsNot24) {
str = `<el-row :gutter="${conf.gutter}"> str = `<el-row :gutter="${conf.gutter}">
${str} ${str}
</el-row>` </el-row>`
} }
return str return str
} }
function buildFromBtns(conf, type) { function buildFromBtns(conf, type) {
let str = '' let str = ''
if (conf.formBtns && type === 'file') { if (conf.formBtns && type === 'file') {
str = `<el-form-item size="large"> str = `<el-form-item size="large">
<el-button type="primary" @click="submitForm">提交</el-button> <el-button type="primary" @click="submitForm">提交</el-button>
<el-button @click="resetForm">重置</el-button> <el-button @click="resetForm">重置</el-button>
</el-form-item>` </el-form-item>`
if (someSpanIsNot24) { if (someSpanIsNot24) {
str = `<el-col :span="24"> str = `<el-col :span="24">
${str} ${str}
</el-col>` </el-col>`
} }
} }
return str return str
} }
// span不为24的用el-col包裹 // span不为24的用el-col包裹
function colWrapper(element, str) { function colWrapper(element, str) {
if (someSpanIsNot24 || element.span !== 24) { if (someSpanIsNot24 || element.span !== 24) {
return `<el-col :span="${element.span}"> return `<el-col :span="${element.span}">
${str} ${str}
</el-col>` </el-col>`
} }
return str return str
} }
const layouts = { const layouts = {
colFormItem(element) { colFormItem(element) {
let labelWidth = '' let labelWidth = ''
if (element.labelWidth && element.labelWidth !== confGlobal.labelWidth) { if (element.labelWidth && element.labelWidth !== confGlobal.labelWidth) {
labelWidth = `label-width="${element.labelWidth}px"` labelWidth = `label-width="${element.labelWidth}px"`
} }
const required = !trigger[element.tag] && element.required ? 'required' : '' const required = !trigger[element.tag] && element.required ? 'required' : ''
const tagDom = tags[element.tag] ? tags[element.tag](element) : null const tagDom = tags[element.tag] ? tags[element.tag](element) : null
let str = `<el-form-item ${labelWidth} label="${element.label}" prop="${element.vModel}" ${required}> let str = `<el-form-item ${labelWidth} label="${element.label}" prop="${element.vModel}" ${required}>
${tagDom} ${tagDom}
</el-form-item>` </el-form-item>`
str = colWrapper(element, str) str = colWrapper(element, str)
return str return str
}, },
rowFormItem(element) { rowFormItem(element) {
const type = element.type === 'default' ? '' : `type="${element.type}"` const type = element.type === 'default' ? '' : `type="${element.type}"`
const justify = element.type === 'default' ? '' : `justify="${element.justify}"` const justify = element.type === 'default' ? '' : `justify="${element.justify}"`
const align = element.type === 'default' ? '' : `align="${element.align}"` const align = element.type === 'default' ? '' : `align="${element.align}"`
const gutter = element.gutter ? `gutter="${element.gutter}"` : '' const gutter = element.gutter ? `gutter="${element.gutter}"` : ''
const children = element.children.map(el => layouts[el.layout](el)) const children = element.children.map(el => layouts[el.layout](el))
let str = `<el-row ${type} ${justify} ${align} ${gutter}> let str = `<el-row ${type} ${justify} ${align} ${gutter}>
${children.join('\n')} ${children.join('\n')}
</el-row>` </el-row>`
str = colWrapper(element, str) str = colWrapper(element, str)
return str return str
} }
} }
const tags = { const tags = {
'el-button': el => { 'el-button': el => {
const { const {
tag, disabled tag, disabled
} = attrBuilder(el) } = attrBuilder(el)
const type = el.type ? `type="${el.type}"` : '' const type = el.type ? `type="${el.type}"` : ''
const icon = el.icon ? `icon="${el.icon}"` : '' const icon = el.icon ? `icon="${el.icon}"` : ''
const size = el.size ? `size="${el.size}"` : '' const size = el.size ? `size="${el.size}"` : ''
let child = buildElButtonChild(el) let child = buildElButtonChild(el)
if (child) child = `\n${child}\n` // 换行 if (child) child = `\n${child}\n` // 换行
return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}</${el.tag}>` return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}</${el.tag}>`
}, },
'el-input': el => { 'el-input': el => {
const { const {
disabled, vModel, clearable, placeholder, width disabled, vModel, clearable, placeholder, width
} = attrBuilder(el) } = attrBuilder(el)
const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : '' const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : ''
const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : '' const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : ''
const readonly = el.readonly ? 'readonly' : '' const readonly = el.readonly ? 'readonly' : ''
const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : '' const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : ''
const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : '' const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : ''
const showPassword = el['show-password'] ? 'show-password' : '' const showPassword = el['show-password'] ? 'show-password' : ''
const type = el.type ? `type="${el.type}"` : '' const type = el.type ? `type="${el.type}"` : ''
const autosize = el.autosize && el.autosize.minRows const autosize = el.autosize && el.autosize.minRows
? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"` ? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"`
: '' : ''
let child = buildElInputChild(el) let child = buildElInputChild(el)
if (child) child = `\n${child}\n` // 换行 if (child) child = `\n${child}\n` // 换行
return `<${el.tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}</${el.tag}>` return `<${el.tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}</${el.tag}>`
}, },
'el-input-number': el => { 'el-input-number': el => {
const { disabled, vModel, placeholder } = attrBuilder(el) const { disabled, vModel, placeholder } = attrBuilder(el)
const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : '' const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : ''
const min = el.min ? `:min='${el.min}'` : '' const min = el.min ? `:min='${el.min}'` : ''
const max = el.max ? `:max='${el.max}'` : '' const max = el.max ? `:max='${el.max}'` : ''
const step = el.step ? `:step='${el.step}'` : '' const step = el.step ? `:step='${el.step}'` : ''
const stepStrictly = el['step-strictly'] ? 'step-strictly' : '' const stepStrictly = el['step-strictly'] ? 'step-strictly' : ''
const precision = el.precision ? `:precision='${el.precision}'` : '' const precision = el.precision ? `:precision='${el.precision}'` : ''
return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${el.tag}>`
}, },
'el-select': el => { 'el-select': el => {
const { const {
disabled, vModel, clearable, placeholder, width disabled, vModel, clearable, placeholder, width
} = attrBuilder(el) } = attrBuilder(el)
const filterable = el.filterable ? 'filterable' : '' const filterable = el.filterable ? 'filterable' : ''
const multiple = el.multiple ? 'multiple' : '' const multiple = el.multiple ? 'multiple' : ''
let child = buildElSelectChild(el) let child = buildElSelectChild(el)
if (child) child = `\n${child}\n` // 换行 if (child) child = `\n${child}\n` // 换行
return `<${el.tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}</${el.tag}>` return `<${el.tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}</${el.tag}>`
}, },
'el-radio-group': el => { 'el-radio-group': el => {
const { disabled, vModel } = attrBuilder(el) const { disabled, vModel } = attrBuilder(el)
const size = `size="${el.size}"` const size = `size="${el.size}"`
let child = buildElRadioGroupChild(el) let child = buildElRadioGroupChild(el)
if (child) child = `\n${child}\n` // 换行 if (child) child = `\n${child}\n` // 换行
return `<${el.tag} ${vModel} ${size} ${disabled}>${child}</${el.tag}>` return `<${el.tag} ${vModel} ${size} ${disabled}>${child}</${el.tag}>`
}, },
'el-checkbox-group': el => { 'el-checkbox-group': el => {
const { disabled, vModel } = attrBuilder(el) const { disabled, vModel } = attrBuilder(el)
const size = `size="${el.size}"` const size = `size="${el.size}"`
const min = el.min ? `:min="${el.min}"` : '' const min = el.min ? `:min="${el.min}"` : ''
const max = el.max ? `:max="${el.max}"` : '' const max = el.max ? `:max="${el.max}"` : ''
let child = buildElCheckboxGroupChild(el) let child = buildElCheckboxGroupChild(el)
if (child) child = `\n${child}\n` // 换行 if (child) child = `\n${child}\n` // 换行
return `<${el.tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}</${el.tag}>` return `<${el.tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}</${el.tag}>`
}, },
'el-switch': el => { 'el-switch': el => {
const { disabled, vModel } = attrBuilder(el) const { disabled, vModel } = attrBuilder(el)
const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : '' const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : ''
const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : '' const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : ''
const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : '' const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : ''
const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : '' const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : ''
const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : '' const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : ''
const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : '' const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : ''
return `<${el.tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${el.tag}>`
}, },
'el-cascader': el => { 'el-cascader': el => {
const { const {
disabled, vModel, clearable, placeholder, width disabled, vModel, clearable, placeholder, width
} = attrBuilder(el) } = attrBuilder(el)
const options = el.options ? `:options="${el.vModel}Options"` : '' const options = el.options ? `:options="${el.vModel}Options"` : ''
const props = el.props ? `:props="${el.vModel}Props"` : '' const props = el.props ? `:props="${el.vModel}Props"` : ''
const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"' const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"'
const filterable = el.filterable ? 'filterable' : '' const filterable = el.filterable ? 'filterable' : ''
const separator = el.separator === '/' ? '' : `separator="${el.separator}"` const separator = el.separator === '/' ? '' : `separator="${el.separator}"`
return `<${el.tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}></${el.tag}>`
}, },
'el-slider': el => { 'el-slider': el => {
const { disabled, vModel } = attrBuilder(el) const { disabled, vModel } = attrBuilder(el)
const min = el.min ? `:min='${el.min}'` : '' const min = el.min ? `:min='${el.min}'` : ''
const max = el.max ? `:max='${el.max}'` : '' const max = el.max ? `:max='${el.max}'` : ''
const step = el.step ? `:step='${el.step}'` : '' const step = el.step ? `:step='${el.step}'` : ''
const range = el.range ? 'range' : '' const range = el.range ? 'range' : ''
const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : '' const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : ''
return `<${el.tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${el.tag}>` return `<${el.tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${el.tag}>`
}, },
'el-time-picker': el => { 'el-time-picker': el => {
const { const {
disabled, vModel, clearable, placeholder, width disabled, vModel, clearable, placeholder, width
} = attrBuilder(el) } = attrBuilder(el)
const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
const isRange = el['is-range'] ? 'is-range' : '' const isRange = el['is-range'] ? 'is-range' : ''
const format = el.format ? `format="${el.format}"` : '' const format = el.format ? `format="${el.format}"` : ''
const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : '' const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : ''
return `<${el.tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${el.tag}>`
}, },
'el-date-picker': el => { 'el-date-picker': el => {
const { const {
disabled, vModel, clearable, placeholder, width disabled, vModel, clearable, placeholder, width
} = attrBuilder(el) } = attrBuilder(el)
const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
const format = el.format ? `format="${el.format}"` : '' const format = el.format ? `format="${el.format}"` : ''
const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
const type = el.type === 'date' ? '' : `type="${el.type}"` const type = el.type === 'date' ? '' : `type="${el.type}"`
const readonly = el.readonly ? 'readonly' : '' const readonly = el.readonly ? 'readonly' : ''
return `<${el.tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}></${el.tag}>` return `<${el.tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}></${el.tag}>`
}, },
'el-rate': el => { 'el-rate': el => {
const { disabled, vModel } = attrBuilder(el) const { disabled, vModel } = attrBuilder(el)
const max = el.max ? `:max='${el.max}'` : '' const max = el.max ? `:max='${el.max}'` : ''
const allowHalf = el['allow-half'] ? 'allow-half' : '' const allowHalf = el['allow-half'] ? 'allow-half' : ''
const showText = el['show-text'] ? 'show-text' : '' const showText = el['show-text'] ? 'show-text' : ''
const showScore = el['show-score'] ? 'show-score' : '' const showScore = el['show-score'] ? 'show-score' : ''
return `<${el.tag} ${vModel} ${allowHalf} ${showText} ${showScore} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${allowHalf} ${showText} ${showScore} ${disabled}></${el.tag}>`
}, },
'el-color-picker': el => { 'el-color-picker': el => {
const { disabled, vModel } = attrBuilder(el) const { disabled, vModel } = attrBuilder(el)
const size = `size="${el.size}"` const size = `size="${el.size}"`
const showAlpha = el['show-alpha'] ? 'show-alpha' : '' const showAlpha = el['show-alpha'] ? 'show-alpha' : ''
const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : '' const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : ''
return `<${el.tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${el.tag}>`
}, },
'el-upload': el => { 'el-upload': el => {
const disabled = el.disabled ? ':disabled=\'true\'' : '' const disabled = el.disabled ? ':disabled=\'true\'' : ''
const action = el.action ? `:action="${el.vModel}Action"` : '' const action = el.action ? `:action="${el.vModel}Action"` : ''
const multiple = el.multiple ? 'multiple' : '' const multiple = el.multiple ? 'multiple' : ''
const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : '' const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : ''
const accept = el.accept ? `accept="${el.accept}"` : '' const accept = el.accept ? `accept="${el.accept}"` : ''
const name = el.name !== 'file' ? `name="${el.name}"` : '' const name = el.name !== 'file' ? `name="${el.name}"` : ''
const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : '' const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : ''
const beforeUpload = `:before-upload="${el.vModel}BeforeUpload"` const beforeUpload = `:before-upload="${el.vModel}BeforeUpload"`
const fileList = `:file-list="${el.vModel}fileList"` const fileList = `:file-list="${el.vModel}fileList"`
const ref = `ref="${el.vModel}"` const ref = `ref="${el.vModel}"`
let child = buildElUploadChild(el) let child = buildElUploadChild(el)
if (child) child = `\n${child}\n` // 换行 if (child) child = `\n${child}\n` // 换行
return `<${el.tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}</${el.tag}>` return `<${el.tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}</${el.tag}>`
} }
} }
function attrBuilder(el) { function attrBuilder(el) {
return { return {
vModel: `v-model="${confGlobal.formModel}.${el.vModel}"`, vModel: `v-model="${confGlobal.formModel}.${el.vModel}"`,
clearable: el.clearable ? 'clearable' : '', clearable: el.clearable ? 'clearable' : '',
placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '', placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '',
width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '', width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '',
disabled: el.disabled ? ':disabled=\'true\'' : '' disabled: el.disabled ? ':disabled=\'true\'' : ''
} }
} }
// el-buttin 子级 // el-buttin 子级
function buildElButtonChild(conf) { function buildElButtonChild(conf) {
const children = [] const children = []
if (conf.default) { if (conf.default) {
children.push(conf.default) children.push(conf.default)
} }
return children.join('\n') return children.join('\n')
} }
// el-input innerHTML // el-input innerHTML
function buildElInputChild(conf) { function buildElInputChild(conf) {
const children = [] const children = []
if (conf.prepend) { if (conf.prepend) {
children.push(`<template slot="prepend">${conf.prepend}</template>`) children.push(`<template slot="prepend">${conf.prepend}</template>`)
} }
if (conf.append) { if (conf.append) {
children.push(`<template slot="append">${conf.append}</template>`) children.push(`<template slot="append">${conf.append}</template>`)
} }
return children.join('\n') return children.join('\n')
} }
function buildElSelectChild(conf) { function buildElSelectChild(conf) {
const children = [] const children = []
if (conf.options && conf.options.length) { if (conf.options && conf.options.length) {
children.push(`<el-option v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`) children.push(`<el-option v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`)
} }
return children.join('\n') return children.join('\n')
} }
function buildElRadioGroupChild(conf) { function buildElRadioGroupChild(conf) {
const children = [] const children = []
if (conf.options && conf.options.length) { if (conf.options && conf.options.length) {
const tag = conf.optionType === 'button' ? 'el-radio-button' : 'el-radio' const tag = conf.optionType === 'button' ? 'el-radio-button' : 'el-radio'
const border = conf.border ? 'border' : '' const border = conf.border ? 'border' : ''
children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`) children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
} }
return children.join('\n') return children.join('\n')
} }
function buildElCheckboxGroupChild(conf) { function buildElCheckboxGroupChild(conf) {
const children = [] const children = []
if (conf.options && conf.options.length) { if (conf.options && conf.options.length) {
const tag = conf.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox' const tag = conf.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox'
const border = conf.border ? 'border' : '' const border = conf.border ? 'border' : ''
children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`) children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
} }
return children.join('\n') return children.join('\n')
} }
function buildElUploadChild(conf) { function buildElUploadChild(conf) {
const list = [] const list = []
if (conf['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>') if (conf['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>')
else list.push(`<el-button size="small" type="primary" icon="el-icon-upload">${conf.buttonText}</el-button>`) else list.push(`<el-button size="small" type="primary" icon="el-icon-upload">${conf.buttonText}</el-button>`)
if (conf.showTip) list.push(`<div slot="tip" class="el-upload__tip">只能上传不超过 ${conf.fileSize}${conf.sizeUnit}${conf.accept}文件</div>`) if (conf.showTip) list.push(`<div slot="tip" class="el-upload__tip">只能上传不超过 ${conf.fileSize}${conf.sizeUnit}${conf.accept}文件</div>`)
return list.join('\n') return list.join('\n')
} }
export function makeUpHtml(conf, type) { export function makeUpHtml(conf, type) {
const htmlList = [] const htmlList = []
confGlobal = conf confGlobal = conf
someSpanIsNot24 = conf.fields.some(item => item.span !== 24) someSpanIsNot24 = conf.fields.some(item => item.span !== 24)
conf.fields.forEach(el => { conf.fields.forEach(el => {
htmlList.push(layouts[el.layout](el)) htmlList.push(layouts[el.layout](el))
}) })
const htmlStr = htmlList.join('\n') const htmlStr = htmlList.join('\n')
let temp = buildFormTemplate(conf, htmlStr, type) let temp = buildFormTemplate(conf, htmlStr, type)
if (type === 'dialog') { if (type === 'dialog') {
temp = dialogWrapper(temp) temp = dialogWrapper(temp)
} }
confGlobal = null confGlobal = null
return temp return temp
} }

View File

@ -1,236 +1,236 @@
import { isArray } from 'util' import { isArray } from 'util'
import { exportDefault, titleCase } from '@/utils/index' import { exportDefault, titleCase } from '@/utils/index'
import { trigger } from './config' import { trigger } from './config'
const units = { const units = {
KB: '1024', KB: '1024',
MB: '1024 / 1024', MB: '1024 / 1024',
GB: '1024 / 1024 / 1024' GB: '1024 / 1024 / 1024'
} }
let confGlobal let confGlobal
const inheritAttrs = { const inheritAttrs = {
file: '', file: '',
dialog: 'inheritAttrs: false,' dialog: 'inheritAttrs: false,'
} }
export function makeUpJs(conf, type) { export function makeUpJs(conf, type) {
confGlobal = conf = JSON.parse(JSON.stringify(conf)) confGlobal = conf = JSON.parse(JSON.stringify(conf))
const dataList = [] const dataList = []
const ruleList = [] const ruleList = []
const optionsList = [] const optionsList = []
const propsList = [] const propsList = []
const methodList = mixinMethod(type) const methodList = mixinMethod(type)
const uploadVarList = [] const uploadVarList = []
conf.fields.forEach(el => { conf.fields.forEach(el => {
buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList)
}) })
const script = buildexport( const script = buildexport(
conf, conf,
type, type,
dataList.join('\n'), dataList.join('\n'),
ruleList.join('\n'), ruleList.join('\n'),
optionsList.join('\n'), optionsList.join('\n'),
uploadVarList.join('\n'), uploadVarList.join('\n'),
propsList.join('\n'), propsList.join('\n'),
methodList.join('\n') methodList.join('\n')
) )
confGlobal = null confGlobal = null
return script return script
} }
function buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) { function buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) {
buildData(el, dataList) buildData(el, dataList)
buildRules(el, ruleList) buildRules(el, ruleList)
if (el.options && el.options.length) { if (el.options && el.options.length) {
buildOptions(el, optionsList) buildOptions(el, optionsList)
if (el.dataType === 'dynamic') { if (el.dataType === 'dynamic') {
const model = `${el.vModel}Options` const model = `${el.vModel}Options`
const options = titleCase(model) const options = titleCase(model)
buildOptionMethod(`get${options}`, model, methodList) buildOptionMethod(`get${options}`, model, methodList)
} }
} }
if (el.props && el.props.props) { if (el.props && el.props.props) {
buildProps(el, propsList) buildProps(el, propsList)
} }
if (el.action && el.tag === 'el-upload') { if (el.action && el.tag === 'el-upload') {
uploadVarList.push( uploadVarList.push(
`${el.vModel}Action: '${el.action}', `${el.vModel}Action: '${el.action}',
${el.vModel}fileList: [],` ${el.vModel}fileList: [],`
) )
methodList.push(buildBeforeUpload(el)) methodList.push(buildBeforeUpload(el))
if (!el['auto-upload']) { if (!el['auto-upload']) {
methodList.push(buildSubmitUpload(el)) methodList.push(buildSubmitUpload(el))
} }
} }
if (el.children) { if (el.children) {
el.children.forEach(el2 => { el.children.forEach(el2 => {
buildAttributes(el2, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) buildAttributes(el2, dataList, ruleList, optionsList, methodList, propsList, uploadVarList)
}) })
} }
} }
function mixinMethod(type) { function mixinMethod(type) {
const list = []; const const list = []; const
minxins = { minxins = {
file: confGlobal.formBtns ? { file: confGlobal.formBtns ? {
submitForm: `submitForm() { submitForm: `submitForm() {
this.$refs['${confGlobal.formRef}'].validate(valid => { this.$refs['${confGlobal.formRef}'].validate(valid => {
if(!valid) return if(!valid) return
// TODO 提交表单 // TODO 提交表单
}) })
},`, },`,
resetForm: `resetForm() { resetForm: `resetForm() {
this.$refs['${confGlobal.formRef}'].resetFields() this.$refs['${confGlobal.formRef}'].resetFields()
},` },`
} : null, } : null,
dialog: { dialog: {
onOpen: 'onOpen() {},', onOpen: 'onOpen() {},',
onClose: `onClose() { onClose: `onClose() {
this.$refs['${confGlobal.formRef}'].resetFields() this.$refs['${confGlobal.formRef}'].resetFields()
},`, },`,
close: `close() { close: `close() {
this.$emit('update:visible', false) this.$emit('update:visible', false)
},`, },`,
handleConfirm: `handleConfirm() { handleConfirm: `handleConfirm() {
this.$refs['${confGlobal.formRef}'].validate(valid => { this.$refs['${confGlobal.formRef}'].validate(valid => {
if(!valid) return if(!valid) return
this.close() this.close()
}) })
},` },`
} }
} }
const methods = minxins[type] const methods = minxins[type]
if (methods) { if (methods) {
Object.keys(methods).forEach(key => { Object.keys(methods).forEach(key => {
list.push(methods[key]) list.push(methods[key])
}) })
} }
return list return list
} }
function buildData(conf, dataList) { function buildData(conf, dataList) {
if (conf.vModel === undefined) return if (conf.vModel === undefined) return
let defaultValue let defaultValue
if (typeof (conf.defaultValue) === 'string' && !conf.multiple) { if (typeof (conf.defaultValue) === 'string' && !conf.multiple) {
defaultValue = `'${conf.defaultValue}'` defaultValue = `'${conf.defaultValue}'`
} else { } else {
defaultValue = `${JSON.stringify(conf.defaultValue)}` defaultValue = `${JSON.stringify(conf.defaultValue)}`
} }
dataList.push(`${conf.vModel}: ${defaultValue},`) dataList.push(`${conf.vModel}: ${defaultValue},`)
} }
function buildRules(conf, ruleList) { function buildRules(conf, ruleList) {
if (conf.vModel === undefined) return if (conf.vModel === undefined) return
const rules = [] const rules = []
if (trigger[conf.tag]) { if (trigger[conf.tag]) {
if (conf.required) { if (conf.required) {
const type = isArray(conf.defaultValue) ? 'type: \'array\',' : '' const type = isArray(conf.defaultValue) ? 'type: \'array\',' : ''
let message = isArray(conf.defaultValue) ? `请至少选择一个${conf.vModel}` : conf.placeholder let message = isArray(conf.defaultValue) ? `请至少选择一个${conf.vModel}` : conf.placeholder
if (message === undefined) message = `${conf.label}不能为空` if (message === undefined) message = `${conf.label}不能为空`
rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`) rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`)
} }
if (conf.regList && isArray(conf.regList)) { if (conf.regList && isArray(conf.regList)) {
conf.regList.forEach(item => { conf.regList.forEach(item => {
if (item.pattern) { if (item.pattern) {
rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`) rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`)
} }
}) })
} }
ruleList.push(`${conf.vModel}: [${rules.join(',')}],`) ruleList.push(`${conf.vModel}: [${rules.join(',')}],`)
} }
} }
function buildOptions(conf, optionsList) { function buildOptions(conf, optionsList) {
if (conf.vModel === undefined) return if (conf.vModel === undefined) return
if (conf.dataType === 'dynamic') { conf.options = [] } if (conf.dataType === 'dynamic') { conf.options = [] }
const str = `${conf.vModel}Options: ${JSON.stringify(conf.options)},` const str = `${conf.vModel}Options: ${JSON.stringify(conf.options)},`
optionsList.push(str) optionsList.push(str)
} }
function buildProps(conf, propsList) { function buildProps(conf, propsList) {
if (conf.dataType === 'dynamic') { if (conf.dataType === 'dynamic') {
conf.valueKey !== 'value' && (conf.props.props.value = conf.valueKey) conf.valueKey !== 'value' && (conf.props.props.value = conf.valueKey)
conf.labelKey !== 'label' && (conf.props.props.label = conf.labelKey) conf.labelKey !== 'label' && (conf.props.props.label = conf.labelKey)
conf.childrenKey !== 'children' && (conf.props.props.children = conf.childrenKey) conf.childrenKey !== 'children' && (conf.props.props.children = conf.childrenKey)
} }
const str = `${conf.vModel}Props: ${JSON.stringify(conf.props.props)},` const str = `${conf.vModel}Props: ${JSON.stringify(conf.props.props)},`
propsList.push(str) propsList.push(str)
} }
function buildBeforeUpload(conf) { function buildBeforeUpload(conf) {
const unitNum = units[conf.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const const unitNum = units[conf.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const
returnList = [] returnList = []
if (conf.fileSize) { if (conf.fileSize) {
rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${conf.fileSize} rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${conf.fileSize}
if(!isRightSize){ if(!isRightSize){
this.$message.error('文件大小超过 ${conf.fileSize}${conf.sizeUnit}') this.$message.error('文件大小超过 ${conf.fileSize}${conf.sizeUnit}')
}` }`
returnList.push('isRightSize') returnList.push('isRightSize')
} }
if (conf.accept) { if (conf.accept) {
acceptCode = `let isAccept = new RegExp('${conf.accept}').test(file.type) acceptCode = `let isAccept = new RegExp('${conf.accept}').test(file.type)
if(!isAccept){ if(!isAccept){
this.$message.error('应该选择${conf.accept}类型的文件') this.$message.error('应该选择${conf.accept}类型的文件')
}` }`
returnList.push('isAccept') returnList.push('isAccept')
} }
const str = `${conf.vModel}BeforeUpload(file) { const str = `${conf.vModel}BeforeUpload(file) {
${rightSizeCode} ${rightSizeCode}
${acceptCode} ${acceptCode}
return ${returnList.join('&&')} return ${returnList.join('&&')}
},` },`
return returnList.length ? str : '' return returnList.length ? str : ''
} }
function buildSubmitUpload(conf) { function buildSubmitUpload(conf) {
const str = `submitUpload() { const str = `submitUpload() {
this.$refs['${conf.vModel}'].submit() this.$refs['${conf.vModel}'].submit()
},` },`
return str return str
} }
function buildOptionMethod(methodName, model, methodList) { function buildOptionMethod(methodName, model, methodList) {
const str = `${methodName}() { const str = `${methodName}() {
// TODO 发起请求获取数据 // TODO 发起请求获取数据
this.${model} this.${model}
},` },`
methodList.push(str) methodList.push(str)
} }
function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods) { function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods) {
const str = `${exportDefault}{ const str = `${exportDefault}{
${inheritAttrs[type]} ${inheritAttrs[type]}
components: {}, components: {},
props: [], props: [],
data () { data () {
return { return {
${conf.formModel}: { ${conf.formModel}: {
${data} ${data}
}, },
${conf.formRules}: { ${conf.formRules}: {
${rules} ${rules}
}, },
${uploadVar} ${uploadVar}
${selectOptions} ${selectOptions}
${props} ${props}
} }
}, },
computed: {}, computed: {},
watch: {}, watch: {},
created () {}, created () {},
mounted () {}, mounted () {},
methods: { methods: {
${methods} ${methods}
} }
}` }`
return str return str
} }

View File

@ -1,199 +1,199 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="用户名称" prop="userName"> <el-form-item label="用户名称" prop="userName">
<el-input <el-input
v-model="queryParams.userName" v-model="queryParams.userName"
placeholder="请输入用户名称" placeholder="请输入用户名称"
clearable clearable
style="width: 240px" style="width: 240px"
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="手机号码" prop="phonenumber"> <el-form-item label="手机号码" prop="phonenumber">
<el-input <el-input
v-model="queryParams.phonenumber" v-model="queryParams.phonenumber"
placeholder="请输入手机号码" placeholder="请输入手机号码"
clearable clearable
style="width: 240px" style="width: 240px"
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <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-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
type="primary" type="primary"
plain plain
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="openSelectUser" @click="openSelectUser"
v-hasPermi="['system:role:add']" v-hasPermi="['system:role:add']"
>添加用户</el-button> >添加用户</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
type="danger" type="danger"
plain plain
icon="el-icon-circle-close" icon="el-icon-circle-close"
size="mini" size="mini"
:disabled="multiple" :disabled="multiple"
@click="cancelAuthUserAll" @click="cancelAuthUserAll"
v-hasPermi="['system:role:remove']" v-hasPermi="['system:role:remove']"
>批量取消授权</el-button> >批量取消授权</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
type="warning" type="warning"
plain plain
icon="el-icon-close" icon="el-icon-close"
size="mini" size="mini"
@click="handleClose" @click="handleClose"
>关闭</el-button> >关闭</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" /> <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" /> <el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" /> <el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status"> <el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/> <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180"> <el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-circle-close" icon="el-icon-circle-close"
@click="cancelAuthUser(scope.row)" @click="cancelAuthUser(scope.row)"
v-hasPermi="['system:role:remove']" v-hasPermi="['system:role:remove']"
>取消授权</el-button> >取消授权</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination <pagination
v-show="total>0" v-show="total>0"
:total="total" :total="total"
:page.sync="queryParams.pageNum" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" :limit.sync="queryParams.pageSize"
@pagination="getList" @pagination="getList"
/> />
<select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery" /> <select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery" />
</div> </div>
</template> </template>
<script> <script>
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role"; import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role";
import selectUser from "./selectUser"; import selectUser from "./selectUser";
export default { export default {
name: "AuthUser", name: "AuthUser",
dicts: ['sys_normal_disable'], dicts: ['sys_normal_disable'],
components: { selectUser }, components: { selectUser },
data() { data() {
return { return {
// 遮罩层 // 遮罩层
loading: true, loading: true,
// 选中用户组 // 选中用户组
userIds: [], userIds: [],
// 非多个禁用 // 非多个禁用
multiple: true, multiple: true,
// 显示搜索条件 // 显示搜索条件
showSearch: true, showSearch: true,
// 总条数 // 总条数
total: 0, total: 0,
// 用户表格数据 // 用户表格数据
userList: [], userList: [],
// 查询参数 // 查询参数
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
roleId: undefined, roleId: undefined,
userName: undefined, userName: undefined,
phonenumber: undefined phonenumber: undefined
} }
}; };
}, },
created() { created() {
const roleId = this.$route.params && this.$route.params.roleId; const roleId = this.$route.params && this.$route.params.roleId;
if (roleId) { if (roleId) {
this.queryParams.roleId = roleId; this.queryParams.roleId = roleId;
this.getList(); this.getList();
} }
}, },
methods: { methods: {
/** 查询授权用户列表 */ /** 查询授权用户列表 */
getList() { getList() {
this.loading = true; this.loading = true;
allocatedUserList(this.queryParams).then(response => { allocatedUserList(this.queryParams).then(response => {
this.userList = response.rows; this.userList = response.rows;
this.total = response.total; this.total = response.total;
this.loading = false; this.loading = false;
} }
); );
}, },
// 返回按钮 // 返回按钮
handleClose() { handleClose() {
const obj = { path: "/system/role" }; const obj = { path: "/system/role" };
this.$tab.closeOpenPage(obj); this.$tab.closeOpenPage(obj);
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1;
this.getList(); this.getList();
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
this.resetForm("queryForm"); this.resetForm("queryForm");
this.handleQuery(); this.handleQuery();
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.userIds = selection.map(item => item.userId) this.userIds = selection.map(item => item.userId)
this.multiple = !selection.length this.multiple = !selection.length
}, },
/** 打开授权用户表弹窗 */ /** 打开授权用户表弹窗 */
openSelectUser() { openSelectUser() {
this.$refs.select.show(); this.$refs.select.show();
}, },
/** 取消授权按钮操作 */ /** 取消授权按钮操作 */
cancelAuthUser(row) { cancelAuthUser(row) {
const roleId = this.queryParams.roleId; const roleId = this.queryParams.roleId;
this.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(function() { this.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(function() {
return authUserCancel({ userId: row.userId, roleId: roleId }); return authUserCancel({ userId: row.userId, roleId: roleId });
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.$modal.msgSuccess("取消授权成功"); this.$modal.msgSuccess("取消授权成功");
}).catch(() => {}); }).catch(() => {});
}, },
/** 批量取消授权按钮操作 */ /** 批量取消授权按钮操作 */
cancelAuthUserAll(row) { cancelAuthUserAll(row) {
const roleId = this.queryParams.roleId; const roleId = this.queryParams.roleId;
const userIds = this.userIds.join(","); const userIds = this.userIds.join(",");
this.$modal.confirm('是否取消选中用户授权数据项?').then(function() { this.$modal.confirm('是否取消选中用户授权数据项?').then(function() {
return authUserCancelAll({ roleId: roleId, userIds: userIds }); return authUserCancelAll({ roleId: roleId, userIds: userIds });
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.$modal.msgSuccess("取消授权成功"); this.$modal.msgSuccess("取消授权成功");
}).catch(() => {}); }).catch(() => {});
} }
} }
}; };
</script> </script>

View File

@ -1,106 +1,106 @@
<template> <template>
<div> <div>
<el-dialog <el-dialog
v-bind="$attrs" v-bind="$attrs"
width="500px" width="500px"
:close-on-click-modal="false" :close-on-click-modal="false"
:modal-append-to-body="false" :modal-append-to-body="false"
v-on="$listeners" v-on="$listeners"
@open="onOpen" @open="onOpen"
@close="onClose" @close="onClose"
> >
<el-row :gutter="15"> <el-row :gutter="15">
<el-form <el-form
ref="elForm" ref="elForm"
:model="formData" :model="formData"
:rules="rules" :rules="rules"
size="medium" size="medium"
label-width="100px" label-width="100px"
> >
<el-col :span="24"> <el-col :span="24">
<el-form-item label="生成类型" prop="type"> <el-form-item label="生成类型" prop="type">
<el-radio-group v-model="formData.type"> <el-radio-group v-model="formData.type">
<el-radio-button <el-radio-button
v-for="(item, index) in typeOptions" v-for="(item, index) in typeOptions"
:key="index" :key="index"
:label="item.value" :label="item.value"
:disabled="item.disabled" :disabled="item.disabled"
> >
{{ item.label }} {{ item.label }}
</el-radio-button> </el-radio-button>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item v-if="showFileName" label="文件名" prop="fileName"> <el-form-item v-if="showFileName" label="文件名" prop="fileName">
<el-input v-model="formData.fileName" placeholder="请输入文件名" clearable /> <el-input v-model="formData.fileName" placeholder="请输入文件名" clearable />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-form> </el-form>
</el-row> </el-row>
<div slot="footer"> <div slot="footer">
<el-button @click="close"> <el-button @click="close">
取消 取消
</el-button> </el-button>
<el-button type="primary" @click="handleConfirm"> <el-button type="primary" @click="handleConfirm">
确定 确定
</el-button> </el-button>
</div> </div>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
inheritAttrs: false, inheritAttrs: false,
props: ['showFileName'], props: ['showFileName'],
data() { data() {
return { return {
formData: { formData: {
fileName: undefined, fileName: undefined,
type: 'file' type: 'file'
}, },
rules: { rules: {
fileName: [{ fileName: [{
required: true, required: true,
message: '请输入文件名', message: '请输入文件名',
trigger: 'blur' trigger: 'blur'
}], }],
type: [{ type: [{
required: true, required: true,
message: '生成类型不能为空', message: '生成类型不能为空',
trigger: 'change' trigger: 'change'
}] }]
}, },
typeOptions: [{ typeOptions: [{
label: '页面', label: '页面',
value: 'file' value: 'file'
}, { }, {
label: '弹窗', label: '弹窗',
value: 'dialog' value: 'dialog'
}] }]
} }
}, },
computed: { computed: {
}, },
watch: {}, watch: {},
mounted() {}, mounted() {},
methods: { methods: {
onOpen() { onOpen() {
if (this.showFileName) { if (this.showFileName) {
this.formData.fileName = `${+new Date()}.vue` this.formData.fileName = `${+new Date()}.vue`
} }
}, },
onClose() { onClose() {
}, },
close(e) { close(e) {
this.$emit('update:visible', false) this.$emit('update:visible', false)
}, },
handleConfirm() { handleConfirm() {
this.$refs.elForm.validate(valid => { this.$refs.elForm.validate(valid => {
if (!valid) return if (!valid) return
this.$emit('confirm', { ...this.formData }) this.$emit('confirm', { ...this.formData })
this.close() this.close()
}) })
} }
} }
} }
</script> </script>

View File

@ -1,149 +1,149 @@
<template> <template>
<div> <div>
<el-dialog <el-dialog
v-bind="$attrs" v-bind="$attrs"
:close-on-click-modal="false" :close-on-click-modal="false"
:modal-append-to-body="false" :modal-append-to-body="false"
v-on="$listeners" v-on="$listeners"
@open="onOpen" @open="onOpen"
@close="onClose" @close="onClose"
> >
<el-row :gutter="0"> <el-row :gutter="0">
<el-form <el-form
ref="elForm" ref="elForm"
:model="formData" :model="formData"
:rules="rules" :rules="rules"
size="small" size="small"
label-width="100px" label-width="100px"
> >
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item
label="选项名" label="选项名"
prop="label" prop="label"
> >
<el-input <el-input
v-model="formData.label" v-model="formData.label"
placeholder="请输入选项名" placeholder="请输入选项名"
clearable clearable
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item
label="选项值" label="选项值"
prop="value" prop="value"
> >
<el-input <el-input
v-model="formData.value" v-model="formData.value"
placeholder="请输入选项值" placeholder="请输入选项值"
clearable clearable
> >
<el-select <el-select
slot="append" slot="append"
v-model="dataType" v-model="dataType"
:style="{width: '100px'}" :style="{width: '100px'}"
> >
<el-option <el-option
v-for="(item, index) in dataTypeOptions" v-for="(item, index) in dataTypeOptions"
:key="index" :key="index"
:label="item.label" :label="item.label"
:value="item.value" :value="item.value"
:disabled="item.disabled" :disabled="item.disabled"
/> />
</el-select> </el-select>
</el-input> </el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-form> </el-form>
</el-row> </el-row>
<div slot="footer"> <div slot="footer">
<el-button <el-button
type="primary" type="primary"
@click="handleConfirm" @click="handleConfirm"
> >
确定 确定
</el-button> </el-button>
<el-button @click="close"> <el-button @click="close">
取消 取消
</el-button> </el-button>
</div> </div>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { isNumberStr } from '@/utils/index' import { isNumberStr } from '@/utils/index'
export default { export default {
components: {}, components: {},
inheritAttrs: false, inheritAttrs: false,
props: [], props: [],
data() { data() {
return { return {
id: 100, id: 100,
formData: { formData: {
label: undefined, label: undefined,
value: undefined value: undefined
}, },
rules: { rules: {
label: [ label: [
{ {
required: true, required: true,
message: '请输入选项名', message: '请输入选项名',
trigger: 'blur' trigger: 'blur'
} }
], ],
value: [ value: [
{ {
required: true, required: true,
message: '请输入选项值', message: '请输入选项值',
trigger: 'blur' trigger: 'blur'
} }
] ]
}, },
dataType: 'string', dataType: 'string',
dataTypeOptions: [ dataTypeOptions: [
{ {
label: '字符串', label: '字符串',
value: 'string' value: 'string'
}, },
{ {
label: '数字', label: '数字',
value: 'number' value: 'number'
} }
] ]
} }
}, },
computed: {}, computed: {},
watch: { watch: {
// eslint-disable-next-line func-names // eslint-disable-next-line func-names
'formData.value': function (val) { 'formData.value': function (val) {
this.dataType = isNumberStr(val) ? 'number' : 'string' this.dataType = isNumberStr(val) ? 'number' : 'string'
} }
}, },
created() {}, created() {},
mounted() {}, mounted() {},
methods: { methods: {
onOpen() { onOpen() {
this.formData = { this.formData = {
label: undefined, label: undefined,
value: undefined value: undefined
} }
}, },
onClose() {}, onClose() {},
close() { close() {
this.$emit('update:visible', false) this.$emit('update:visible', false)
}, },
handleConfirm() { handleConfirm() {
this.$refs.elForm.validate(valid => { this.$refs.elForm.validate(valid => {
if (!valid) return if (!valid) return
if (this.dataType === 'number') { if (this.dataType === 'number') {
this.formData.value = parseFloat(this.formData.value) this.formData.value = parseFloat(this.formData.value)
} }
this.formData.id = this.id++ this.formData.id = this.id++
this.$emit('commit', this.formData) this.$emit('commit', this.formData)
this.close() this.close()
}) })
} }
} }
} }
</script> </script>

286
ruoyi/pom.xml Normal file
View File

@ -0,0 +1,286 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>ruoyi</artifactId>
<description>
web服务入口
</description>
<dependencies>
<!-- SpringBoot Web容器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- web 容器使用 undertow 性能更强 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-javadoc</artifactId>
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- Oracle -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
</dependency>
<!-- PostgreSql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- SqlServer -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
</dependency>
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- JSON工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<!-- servlet包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- dynamic-datasource 多数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- sql性能分析插件 -->
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-jwt</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 自动生成YML配置关联JSON文件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-27</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
</dependency>
<!-- 加密包引入 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
</dependency>
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
</dependency>
<!--短信sms4j-->
<dependency>
<groupId>org.dromara.sms4j</groupId>
<artifactId>sms4j-spring-boot-starter</artifactId>
</dependency>
<!-- 离线IP地址定位库 ip2region -->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- skywalking 整合 logback -->
<!-- <dependency>-->
<!-- <groupId>org.apache.skywalking</groupId>-->
<!-- <artifactId>apm-toolkit-logback-1.x</artifactId>-->
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.skywalking</groupId>-->
<!-- <artifactId>apm-toolkit-trace</artifactId>-->
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
</plugins>
</build>
</project>

Some files were not shown because too many files have changed in this diff Show More