104 Commits

Author SHA1 Message Date
mpaster
62f760ee66 Pre Merge pull request !436 from mpaster/cherry-pick-1759037399 2025-12-05 07:10:10 +00:00
RuoYi
d488b79c2d 优化用户序列化忽略密码字段 2025-12-05 15:09:48 +08:00
RuoYi
f53b783049 优化数据权限控制逻辑,放开permission限制 2025-12-04 17:35:47 +08:00
RuoYi
97f30a5415 支持Excel导出对象的多个子列表 2025-12-04 16:48:19 +08:00
RuoYi
ad1d009165 升级tomcat到最新版本9.0.112 2025-12-04 16:43:11 +08:00
RuoYi
90cbabb7a7 优化代码 2025-12-04 16:42:55 +08:00
RuoYi
1c4dbb1e46 优化表单构建关闭页签销毁复制插件 2025-12-04 13:15:50 +08:00
RuoYi
a3eefb6bad 优化生成代码下载的zip文件名 2025-12-03 10:27:23 +08:00
RuoYi
09e8e9995a 网页标题设置新增SET_TITLE方法 2025-12-02 19:31:23 +08:00
RuoYi
381151bc50 支持Excel导出对象的多个子列表 2025-12-02 19:14:04 +08:00
RuoYi
66e502727a 登录/注册页面底部版权信息修改为读取配置 2025-12-02 15:34:27 +08:00
RuoYi
4265f8ecb7 修复v3时间控件between选择后清空报错问题 2025-12-02 15:00:36 +08:00
RuoYi
2c82079d04 修复表单构建移除所有控件后切换路由回来空白问题 2025-12-02 13:12:55 +08:00
RuoYi
6aecd35a4f 修复combo属性过多sheet出现的异常问题 2025-11-13 11:58:03 +08:00
mpaster
697d1f0d77 支持菜单修改时图标可置空。 2025-09-28 05:30:32 +00:00
RuoYi
ac92ae3ae6 修复固定头部时出现的导航栏偏移问题 2025-09-04 20:06:26 +08:00
RuoYi
1d2c8378f7 文件支持防盗链配置 2025-09-02 13:26:33 +08:00
RuoYi
50a9337ee8 优化代码 2025-08-28 13:51:15 +08:00
RuoYi
e6a3415a71 优化代码 2025-08-27 16:01:28 +08:00
RuoYi
7919af54da 用户导入添加验证提示 2025-08-23 11:46:49 +08:00
RuoYi
3503005f9d 优化布局设置显示 2025-08-23 11:46:39 +08:00
RuoYi
b304a41194 修复用户归属部门无法修改为空问题 2025-08-21 14:59:10 +08:00
RuoYi
a39ae33c82 columns default value 2025-08-09 16:13:49 +08:00
RuoYi
b9a27657c5 显示列信息支持对象格式 2025-08-09 15:19:13 +08:00
RuoYi
2e009841ca 自动识别json对象白名单配置范围缩小 2025-08-09 15:18:29 +08:00
RuoYi
2cbe4a8234 升级tomcat到最新版本9.0.108 2025-08-09 15:17:10 +08:00
RuoYi
4b37049713 添加新群号:112869560 2025-07-19 19:28:44 +08:00
RuoYi
e549210ad6 优化定时任务包名白名单匹配方式 2025-06-20 11:56:03 +08:00
RuoYi
ad988d54bb 优化Excel统计行数值的单元格样式显示 2025-06-19 14:54:00 +08:00
RuoYi
51a6fce0a5 升级tomcat到最新版本9.0.106 2025-06-18 13:41:37 +08:00
RuoYi
c86bfa9243 用户头像更换后移除旧头像文件 2025-06-06 19:36:36 +08:00
RuoYi
8aca11c2a2 若依 3.6.6 2025-05-30 08:03:00 +08:00
RuoYi
725033e361 升级fastjson到最新版2.0.57 2025-05-26 11:14:45 +08:00
RuoYi
d29e49e23b 注册账号设置默认密码最后更新时间 2025-05-26 11:14:06 +08:00
RuoYi
706c3bb69b 添加底部版权信息及开关 2025-05-24 14:33:51 +08:00
RuoYi
cd0ee95b9c 添加页签图标显示开关功能 2025-05-23 14:57:49 +08:00
RuoYi
3293e2fb56 账号密码支持自定义更新周期 2025-05-23 10:19:47 +08:00
RuoYi
924ec0eb6e 初始密码支持自定义修改策略 2025-05-23 09:58:23 +08:00
RuoYi
135b1204a9 升级tomcat到最新版本9.0.105 2025-05-15 10:55:18 +08:00
RuoYi
cb566a704b 升级commons.io到最新版本2.19.0 2025-05-15 10:23:50 +08:00
RuoYi
aadba0382e delete vue-meta 2025-05-15 10:23:34 +08:00
RuoYi
a0ce1cf33b delete eslint 2025-05-15 10:22:46 +08:00
RuoYi
3915c77391 优化导航栏显示昵称&设置 2025-05-09 14:02:09 +08:00
RuoYi
b80932ceb4 菜单搜索支持键盘选择&悬浮主题背景 2025-05-07 13:27:13 +08:00
RuoYi
056cf94082 图片上传组件新增disabled属性 2025-05-06 19:14:54 +08:00
RuoYi
0dcd3e6183 add columnName Drag 2025-05-06 14:54:44 +08:00
RuoYi
07be5ceb26 修复上传组件被多次引用拖动仅对第一个有效的问题 2025-05-06 13:46:21 +08:00
RuoYi
cc59502d7c update icon 2025-05-05 11:22:35 +08:00
RuoYi
98738f23ad 上传组件新增拖动排序属性 2025-04-30 10:31:03 +08:00
RuoYi
57fe1c663e 优化Excel匹配数值型.0结尾 2025-04-28 11:20:48 +08:00
RuoYi
7b6fdb3a89 remove all semicolons 2025-04-27 11:56:21 +08:00
RuoYi
79c885decb 使用Gateway CacheRequestBody代替CacheRequestFilter 2025-04-25 15:11:17 +08:00
RuoYi
1a0f37a2dc 富文本复制粘贴图片上传至url 2025-04-24 18:19:16 +08:00
RuoYi
02de344d8c update package.json 2025-04-24 18:18:44 +08:00
RuoYi
189100f74e 优化低版本node无法启动的问题 2025-04-22 12:07:07 +08:00
RuoYi
e29284e687 优化代码 2025-04-22 12:06:59 +08:00
RuoYi
d4af286f41 显隐列组件支持全选/全不选 2025-04-21 15:30:32 +08:00
RuoYi
60e2d55a23 优化菜单搜索查询页 2025-04-21 13:28:32 +08:00
RuoYi
bbd112d5a3 支持文件&图片组件自定义地址&参数 2025-04-18 13:25:28 +08:00
RuoYi
90922844ea 优化角色禁用不允许分配 2025-04-17 15:36:18 +08:00
RuoYi
3a9f56f04b update status name 2025-04-17 15:35:58 +08:00
RuoYi
a1ec1d57d4 remove dev runjs 2025-03-18 16:01:46 +08:00
RuoYi
060959a7c5 登录页和注册页表头使用VUE_APP_TITLE配置值 2025-03-18 16:01:20 +08:00
RuoYi
43e1d8d573 升级tomcat到最新版本9.0.102 2025-03-14 16:12:40 +08:00
RuoYi
67cf51ba77 update handleTree 2025-03-14 16:12:29 +08:00
RuoYi
a256618d5d 优化代码 2025-03-11 12:52:17 +08:00
若依
a6bcebb62b !397 修复actuator暴漏问题
Merge pull request !397 from 威士忌的纯度/N/A
2025-03-10 03:45:34 +00:00
威士忌的纯度
1cb262daa3 修复actuator暴漏问题
Signed-off-by: 威士忌的纯度 <whr888888@vip.qq.com>
2025-03-07 10:22:52 +00:00
RuoYi
8c096cba8d 优化isAdmin方法,避免脱敏模块security依赖 2025-03-07 12:56:31 +08:00
RuoYi
088cec8adf 菜单管理新增路由名称 2025-03-06 11:09:34 +08:00
RuoYi
85ff6a9910 优化顶部菜单搜索栏为多层级显示 2025-03-05 18:14:13 +08:00
RuoYi
cab5beaca7 文件上传组件新增disabled属性&类型 2025-03-05 18:13:40 +08:00
RuoYi
fc8069a250 优化导出Excel日期格式双击离开后与设定的格式不一致问题 2025-03-05 18:13:12 +08:00
RuoYi
924e705dca 代码生成列表支持按时间排序 2025-03-05 18:12:52 +08:00
RuoYi
049ba453d1 优化空指针异常时无法获取错误信息问题 2025-03-05 18:10:56 +08:00
RuoYi
4aa261e8f7 优化定时任务字符包含多个括号导致数据错误 2025-03-05 18:10:12 +08:00
RuoYi
914a6620f5 升级tomcat到最新版本9.0.98 2025-03-05 18:08:29 +08:00
RuoYi
3dcee7057d 优化代码 2025-03-05 18:01:33 +08:00
RuoYi
0467631319 update ry_config.sql 2025-02-24 16:24:36 +08:00
若依
a11df90255 !393 config(nacos):增加nacos2.5.0配置文件sql
Merge pull request !393 from 牟雷/master
2025-02-18 00:33:39 +00:00
牟雷
596e4fe756 config(nacos):增加nacos2.5.0配置文件sql 2025-02-17 20:19:22 +08:00
RuoYi
37219e4ae6 copyright 2025 2025-01-07 10:55:58 +08:00
RuoYi
adaa3e1db8 代码生成新增配置是否允许文件覆盖到本地 2024-12-25 16:30:44 +08:00
RuoYi
88ad5a2c19 优化导入带标题文件关闭清理 2024-12-25 16:24:38 +08:00
RuoYi
b45dc2ec25 update sqlkeyword 2024-12-25 16:24:02 +08:00
RuoYi
67b17da06f 优化特殊字符密码修改失败问题 2024-12-17 14:28:17 +08:00
RuoYi
b25a280ebb 优化TopNav内链菜单点击没有高亮(IB8WHJ) 2024-12-17 11:57:05 +08:00
RuoYi
cc026e75a3 优化菜单管理切换Mini布局错乱问题 2024-12-17 11:25:03 +08:00
RuoYi
7216b56a56 用户管理过滤掉已禁用部门 2024-12-11 11:43:00 +08:00
RuoYi
a326e880a1 修改主题样式本地读取 2024-12-07 17:08:53 +08:00
RuoYi
92c6d21855 优化文件异常输入流未关闭的问题 2024-12-05 14:27:54 +08:00
RuoYi
2335157f6e 白名单支持对通配符路径匹配 2024-12-04 08:52:13 +08:00
RuoYi
6c3b01c3c5 Excel注解支持wrapText是否允许内容换行 2024-12-03 09:07:04 +08:00
RuoYi
8faea60191 修复导出子列表对象只能在最后的问题 2024-12-02 20:37:12 +08:00
RuoYi
28a16d9878 修复默认关闭Tags-Views时,内链页面打不开 2024-11-27 19:49:12 +08:00
RuoYi
dd3cf18e27 修复TopNav无法正确获取active的问题 2024-11-27 09:02:26 +08:00
RuoYi
65d03dc014 优化代码 2024-11-25 22:30:03 +08:00
RuoYi
7912fd81bd 面板兼容移动端显示 2024-11-25 15:41:00 +08:00
RuoYi
e2175e5b9d 参数键值更换为多行文本 2024-11-25 12:15:49 +08:00
RuoYi
c0e119f8e0 菜单面包屑导航支持多层级显示 2024-11-22 20:45:08 +08:00
RuoYi
fa77b2a08c 分栏参数微调 2024-11-22 14:46:59 +08:00
RuoYi
a222c24796 用户管理支持分栏拖动 2024-11-22 13:58:37 +08:00
RuoYi
08f4b877ce 优化代码 2024-11-20 11:13:24 +08:00
RuoYi
aa607d135c update .env.staging 2024-11-20 10:43:07 +08:00
186 changed files with 4149 additions and 3641 deletions

View File

@@ -1,11 +1,11 @@
<p align="center"> <p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png"> <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
</p> </p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.5</h1> <h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.6</h1>
<h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4> <h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
<p align="center"> <p align="center">
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.5-brightgreen.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.6-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p> </p>
@@ -126,4 +126,4 @@ com.ruoyi
## 若依微服务交流群 ## 若依微服务交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/已满-158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) [![加入QQ群](https://img.shields.io/badge/112869560-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Kuaw0Xdlw2Nlgn6s8h9elzuquHGxGObD&authKey=cSrQcWQ%2BzQZAFFrwxaR%2BbzcumX4WRduZnd1O6JO1dlclQMiu%2BKwxAy8t2JfNp67V&noverify=0&group_code=112869560) 点击按钮入群。

View File

@@ -9,8 +9,8 @@ usage() {
# copy sql # copy sql
echo "begin copy sql " echo "begin copy sql "
cp ../sql/ry_20240629.sql ./mysql/db cp ../sql/ry_20250523.sql ./mysql/db
cp ../sql/ry_config_20240902.sql ./mysql/db cp ../sql/ry_config_20250224.sql ./mysql/db
# copy html # copy html
echo "begin copy html " echo "begin copy html "

View File

@@ -29,7 +29,7 @@ http {
} }
# 避免actuator暴露 # 避免actuator暴露
if ($request_uri ~ "/actuator") { if ($uri ~ "/actuator") {
return 403; return 403;
} }

11
pom.xml
View File

@@ -6,14 +6,14 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description> <description>若依微服务系统</description>
<properties> <properties>
<ruoyi.version>3.6.5</ruoyi.version> <ruoyi.version>3.6.6</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
@@ -26,17 +26,16 @@
<pagehelper.boot.version>2.0.0</pagehelper.boot.version> <pagehelper.boot.version>2.0.0</pagehelper.boot.version>
<druid.version>1.2.23</druid.version> <druid.version>1.2.23</druid.version>
<dynamic-ds.version>4.3.1</dynamic-ds.version> <dynamic-ds.version>4.3.1</dynamic-ds.version>
<commons.io.version>2.13.0</commons.io.version> <commons.io.version>2.19.0</commons.io.version>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<fastjson.version>2.0.53</fastjson.version> <fastjson.version>2.0.57</fastjson.version>
<jjwt.version>0.9.1</jjwt.version> <jjwt.version>0.9.1</jjwt.version>
<minio.version>8.2.2</minio.version> <minio.version>8.2.2</minio.version>
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<springdoc.version>1.6.9</springdoc.version> <springdoc.version>1.6.9</springdoc.version>
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version> <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
<!-- override dependency version --> <!-- override dependency version -->
<tomcat.version>9.0.96</tomcat.version> <tomcat.version>9.0.112</tomcat.version>
<logback.version>1.2.13</logback.version> <logback.version>1.2.13</logback.version>
<spring-framework.version>5.3.39</spring-framework.version> <spring-framework.version>5.3.39</spring-framework.version>
</properties> </properties>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api</artifactId> <artifactId>ruoyi-api</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -2,7 +2,9 @@ package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.constant.ServiceNameConstants; import com.ruoyi.common.core.constant.ServiceNameConstants;
@@ -26,4 +28,13 @@ public interface RemoteFileService
*/ */
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file); public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file);
/**
* 删除文件
*
* @param fileUrl 文件地址
* @return 结果
*/
@DeleteMapping(value = "/delete", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public R<Boolean> delete(@RequestParam("fileUrl") String fileUrl);
} }

View File

@@ -5,10 +5,12 @@ import java.util.List;
import javax.validation.constraints.*; import javax.validation.constraints.*;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.annotation.Excel.ColumnType; import com.ruoyi.common.core.annotation.Excel.ColumnType;
import com.ruoyi.common.core.annotation.Excel.Type; import com.ruoyi.common.core.annotation.Excel.Type;
import com.ruoyi.common.core.annotation.Excels; import com.ruoyi.common.core.annotation.Excels;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.core.xss.Xss; import com.ruoyi.common.core.xss.Xss;
@@ -55,8 +57,8 @@ public class SysUser extends BaseEntity
/** 密码 */ /** 密码 */
private String password; private String password;
/** 号状态0正常 1停用 */ /** 号状态0正常 1停用 */
@Excel(name = "号状态", readConverterExp = "0=正常,1=停用") @Excel(name = "号状态", readConverterExp = "0=正常,1=停用")
private String status; private String status;
/** 删除标志0代表存在 2代表删除 */ /** 删除标志0代表存在 2代表删除 */
@@ -70,6 +72,9 @@ public class SysUser extends BaseEntity
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate; private Date loginDate;
/** 密码最后更新时间 */
private Date pwdUpdateDate;
/** 部门对象 */ /** 部门对象 */
@Excels({ @Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@@ -116,7 +121,7 @@ public class SysUser extends BaseEntity
public static boolean isAdmin(Long userId) public static boolean isAdmin(Long userId)
{ {
return userId != null && 1L == userId; return UserConstants.isAdmin(userId);
} }
public Long getDeptId() public Long getDeptId()
@@ -197,6 +202,7 @@ public class SysUser extends BaseEntity
this.avatar = avatar; this.avatar = avatar;
} }
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
public String getPassword() public String getPassword()
{ {
return password; return password;
@@ -247,6 +253,16 @@ public class SysUser extends BaseEntity
this.loginDate = loginDate; this.loginDate = loginDate;
} }
public Date getPwdUpdateDate()
{
return pwdUpdateDate;
}
public void setPwdUpdateDate(Date pwdUpdateDate)
{
this.pwdUpdateDate = pwdUpdateDate;
}
public SysDept getDept() public SysDept getDept()
{ {
return dept; return dept;
@@ -296,6 +312,7 @@ public class SysUser extends BaseEntity
{ {
this.roleId = roleId; this.roleId = roleId;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -312,6 +329,7 @@ public class SysUser extends BaseEntity
.append("delFlag", getDelFlag()) .append("delFlag", getDelFlag())
.append("loginIp", getLoginIp()) .append("loginIp", getLoginIp())
.append("loginDate", getLoginDate()) .append("loginDate", getLoginDate())
.append("pwdUpdateDate", getPwdUpdateDate())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())

View File

@@ -30,6 +30,12 @@ public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileServ
{ {
return R.fail("上传文件失败:" + throwable.getMessage()); return R.fail("上传文件失败:" + throwable.getMessage());
} }
@Override
public R<Boolean> delete(String fileUrl)
{
return R.fail("删除文件失败:" + throwable.getMessage());
}
}; };
} }
} }

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -143,6 +143,7 @@ public class SysLoginService
SysUser sysUser = new SysUser(); SysUser sysUser = new SysUser();
sysUser.setUserName(username); sysUser.setUserName(username);
sysUser.setNickName(username); sysUser.setNickName(username);
sysUser.setPwdUpdateDate(DateUtils.getNowDate());
sysUser.setPassword(SecurityUtils.encryptPassword(password)); sysUser.setPassword(SecurityUtils.encryptPassword(password));
R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER); R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -78,6 +78,11 @@ public @interface Excel
*/ */
public String prompt() default ""; public String prompt() default "";
/**
* 是否允许内容换行
*/
public boolean wrapText() default false;
/** /**
* 设置只能选择不能输入的列内容. * 设置只能选择不能输入的列内容.
*/ */

View File

@@ -87,6 +87,16 @@ public class Constants
*/ */
public static final String LOGIN_FAIL = "Error"; public static final String LOGIN_FAIL = "Error";
/**
* 所有权限标识
*/
public static final String ALL_PERMISSION = "*:*:*";
/**
* 管理员角色权限标识
*/
public static final String SUPER_ADMIN = "admin";
/** /**
* 当前记录起始索引 * 当前记录起始索引
*/ */
@@ -120,7 +130,7 @@ public class Constants
/** /**
* 自动识别json对象白名单配置仅允许解析的包名范围越小越安全 * 自动识别json对象白名单配置仅允许解析的包名范围越小越安全
*/ */
public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" }; public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" };
/** /**
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)

View File

@@ -80,4 +80,9 @@ public class UserConstants
public static final int PASSWORD_MIN_LENGTH = 5; public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20; public static final int PASSWORD_MAX_LENGTH = 20;
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
} }

View File

@@ -540,9 +540,9 @@ public class Convert
/** /**
* 转换为boolean<br> * 转换为boolean<br>
* String支持的值为true、false、yes、ok、no1,0 如果给定的值为空,或者转换失败,返回默认值<br> * String支持的值为true、false、yes、ok、no、1、0、是、否, 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@@ -569,10 +569,12 @@ public class Convert
case "yes": case "yes":
case "ok": case "ok":
case "1": case "1":
case "":
return true; return true;
case "false": case "false":
case "no": case "no":
case "0": case "0":
case "":
return false; return false;
default: default:
return defaultValue; return defaultValue;

View File

@@ -136,6 +136,14 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
return new Date(time); return new Date(time);
} }
/**
* 计算相差天数
*/
public static int differentDaysByMillisecond(Date date1, Date date2)
{
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/** /**
* 计算时间差 * 计算时间差
* *

View File

@@ -283,6 +283,32 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return str.substring(start, end); return str.substring(start, end);
} }
/**
* 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串
*
* @param str 要截取的字符串
* @param open 起始字符串
* @param close 结束字符串
* @return 截取结果
*/
public static String substringBetweenLast(final String str, final String open, final String close)
{
if (isEmpty(str) || isEmpty(open) || isEmpty(close))
{
return NULLSTR;
}
final int start = str.indexOf(open);
if (start != INDEX_NOT_FOUND)
{
final int end = str.lastIndexOf(close);
if (end != INDEX_NOT_FOUND)
{
return str.substring(start + open.length(), end);
}
}
return NULLSTR;
}
/** /**
* 判断是否为空,并且不是空白字符 * 判断是否为空,并且不是空白字符
* *

View File

@@ -114,20 +114,20 @@ public class FileUtils
} }
/** /**
* 检查文件是否可下载 * 校验文件路径合法性(安全性与扩展名)
* *
* @param resource 需要下载的文件 * @param fileUrl 待校验的文件地址
* @return true 正常 false 非法 * @return true 正常 false 非法
*/ */
public static boolean checkAllowDownload(String resource) public static boolean validateFilePath(String fileUrl)
{ {
// 禁止目录上跳级别 // 禁止目录上跳级别
if (StringUtils.contains(resource, "..")) if (StringUtils.contains(fileUrl, ".."))
{ {
return false; return false;
} }
// 判断是否在允许下载的文件规则内 // 判断是否在允许下载的文件规则内
return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)); return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(fileUrl));
} }
/** /**

View File

@@ -73,6 +73,8 @@ public class ExcelUtil<T>
{ {
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public static final String SEPARATOR = ",";
public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
@@ -145,23 +147,18 @@ public class ExcelUtil<T>
/** /**
* 对象的子列表方法 * 对象的子列表方法
*/ */
private Method subMethod; private Map<String, Method> subMethods;
/** /**
* 对象的子列表属性 * 对象的子列表属性
*/ */
private List<Field> subFields; private Map<String, List<Field>> subFieldsMap;
/** /**
* 统计列表 * 统计列表
*/ */
private Map<Integer, Double> statistics = new HashMap<Integer, Double>(); private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/** /**
* 实体对象 * 实体对象
*/ */
@@ -225,19 +222,20 @@ public class ExcelUtil<T>
{ {
if (StringUtils.isNotEmpty(title)) if (StringUtils.isNotEmpty(title))
{ {
subMergedFirstRowNum++;
subMergedLastRowNum++;
int titleLastCol = this.fields.size() - 1; int titleLastCol = this.fields.size() - 1;
if (isSubList()) if (isSubList())
{ {
titleLastCol = titleLastCol + subFields.size() - 1; for (List<Field> currentSubFields : subFieldsMap.values())
{
titleLastCol = titleLastCol + currentSubFields.size() - 1;
}
} }
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
titleRow.setHeightInPoints(30); titleRow.setHeightInPoints(30);
Cell titleCell = titleRow.createCell(0); Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title")); titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title); titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol)); sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol));
} }
} }
@@ -248,23 +246,32 @@ public class ExcelUtil<T>
{ {
if (isSubList()) if (isSubList())
{ {
subMergedFirstRowNum++;
subMergedLastRowNum++;
Row subRow = sheet.createRow(rownum); Row subRow = sheet.createRow(rownum);
int excelNum = 0; int column = 0;
for (Object[] objects : fields) for (Object[] objects : fields)
{ {
Field field = (Field) objects[0];
Excel attr = (Excel) objects[1]; Excel attr = (Excel) objects[1];
Cell headCell1 = subRow.createCell(excelNum); CellStyle cellStyle = styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()));
headCell1.setCellValue(attr.name()); if (Collection.class.isAssignableFrom(field.getType()))
headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); {
excelNum++; Cell cell = subRow.createCell(column);
} cell.setCellValue(attr.name());
int headFirstRow = excelNum - 1; cell.setCellStyle(cellStyle);
int headLastRow = headFirstRow + subFields.size() - 1; int subFieldSize = subFieldsMap != null ? subFieldsMap.get(field.getName()).size() : 0;
if (headLastRow > headFirstRow) if (subFieldSize > 1)
{ {
sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow)); CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
sheet.addMergedRegion(cellAddress);
}
column += subFieldSize;
}
else
{
Cell cell = subRow.createCell(column++);
cell.setCellValue(attr.name());
cell.setCellStyle(cellStyle);
}
} }
rownum++; rownum++;
} }
@@ -277,11 +284,23 @@ public class ExcelUtil<T>
* @return 转换后集合 * @return 转换后集合
*/ */
public List<T> importExcel(InputStream is) public List<T> importExcel(InputStream is)
{
return importExcel(is, 0);
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum)
{ {
List<T> list = null; List<T> list = null;
try try
{ {
list = importExcel(is, 0); list = importExcel(StringUtils.EMPTY, is, titleNum);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -295,18 +314,6 @@ public class ExcelUtil<T>
return list; return list;
} }
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum) throws Exception
{
return importExcel(StringUtils.EMPTY, is, titleNum);
}
/** /**
* 对excel表单指定表格索引名转换成list * 对excel表单指定表格索引名转换成list
* *
@@ -335,7 +342,11 @@ public class ExcelUtil<T>
Map<String, Integer> cellMap = new HashMap<String, Integer>(); Map<String, Integer> cellMap = new HashMap<String, Integer>();
// 获取表头 // 获取表头
Row heard = sheet.getRow(titleNum); Row heard = sheet.getRow(titleNum);
for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) if (heard == null)
{
throw new UtilException("文件标题行为空请检查Excel文件格式");
}
for (int i = 0; i < heard.getLastCellNum(); i++)
{ {
Cell cell = heard.getCell(i); Cell cell = heard.getCell(i);
if (StringUtils.isNotNull(cell)) if (StringUtils.isNotNull(cell))
@@ -343,10 +354,6 @@ public class ExcelUtil<T>
String value = this.getCellValue(heard, i).toString(); String value = this.getCellValue(heard, i).toString();
cellMap.put(value, i); cellMap.put(value, i);
} }
else
{
cellMap.put(null, i);
}
} }
// 有数据时才处理 得到类的所有field. // 有数据时才处理 得到类的所有field.
List<Object[]> fields = this.getFields(); List<Object[]> fields = this.getFields();
@@ -384,7 +391,7 @@ public class ExcelUtil<T>
if (String.class == fieldType) if (String.class == fieldType)
{ {
String s = Convert.toStr(val); String s = Convert.toStr(val);
if (StringUtils.endsWith(s, ".0")) if (s.matches("^\\d+\\.0$"))
{ {
val = StringUtils.substringBefore(s, ".0"); val = StringUtils.substringBefore(s, ".0");
} }
@@ -559,7 +566,8 @@ public class ExcelUtil<T>
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
for (Field subField : subFields) List<Field> currentSubFields = subFieldsMap.get(field.getName());
for (Field subField : currentSubFields)
{ {
Excel subExcel = subField.getAnnotation(Excel.class); Excel subExcel = subField.getAnnotation(Excel.class);
this.createHeadCell(subExcel, row, column++); this.createHeadCell(subExcel, row, column++);
@@ -572,7 +580,7 @@ public class ExcelUtil<T>
} }
if (Type.EXPORT.equals(type)) if (Type.EXPORT.equals(type))
{ {
fillExcelData(index, row); fillExcelData(index);
addStatisticsRow(); addStatisticsRow();
} }
} }
@@ -582,71 +590,98 @@ public class ExcelUtil<T>
* 填充excel数据 * 填充excel数据
* *
* @param index 序号 * @param index 序号
* @param row 单元格行
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void fillExcelData(int index, Row row) public void fillExcelData(int index)
{ {
int startNo = index * sheetSize; int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size()); int endNo = Math.min(startNo + sheetSize, list.size());
int rowNo = (1 + rownum) - startNo; int currentRowNum = rownum + 1; // 从标题行后开始
for (int i = startNo; i < endNo; i++) for (int i = startNo; i < endNo; i++)
{ {
rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo; Row row = sheet.createRow(currentRowNum);
row = sheet.createRow(rowNo);
// 得到导出对象.
T vo = (T) list.get(i); T vo = (T) list.get(i);
Collection<?> subList = null;
if (isSubList())
{
if (isSubListValue(vo))
{
subList = getListCellValue(vo);
subMergedLastRowNum = subMergedLastRowNum + subList.size();
}
else
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
}
}
int column = 0; int column = 0;
int maxSubListSize = getCurrentMaxSubListSize(vo);
for (Object[] os : fields) for (Object[] os : fields)
{ {
Field field = (Field) os[0]; Field field = (Field) os[0];
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) if (Collection.class.isAssignableFrom(field.getType()))
{ {
boolean subFirst = false; try
for (Object obj : subList)
{ {
if (subFirst) Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
List<Field> currentSubFields = subFieldsMap.get(field.getName());
if (subList != null && !subList.isEmpty())
{ {
rowNo++; int subIndex = 0;
row = sheet.createRow(rowNo); for (Object subVo : subList)
}
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
int subIndex = 0;
for (Field subField : subFields)
{
if (subField.isAnnotationPresent(Excel.class))
{ {
subField.setAccessible(true); Row subRow = sheet.getRow(currentRowNum + subIndex);
Excel attr = subField.getAnnotation(Excel.class); if (subRow == null)
this.addCell(attr, row, (T) obj, subField, column + subIndex); {
subRow = sheet.createRow(currentRowNum + subIndex);
}
int subColumn = column;
for (Field subField : currentSubFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
}
subIndex++;
} }
subIndex++;
} }
subFirst = true; column += currentSubFields.size();
}
catch (Exception e)
{
log.error("填充集合数据失败", e);
} }
this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
} }
else else
{ {
this.addCell(excel, row, vo, field, column++); // 创建单元格并设置值
addCell(excel, row, vo, field, column);
if (maxSubListSize > 1 && excel.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
}
column++;
}
}
currentRowNum += maxSubListSize;
}
}
/**
* 获取子列表最大数
*/
private int getCurrentMaxSubListSize(T vo)
{
int maxSubListSize = 1;
for (Object[] os : fields)
{
Field field = (Field) os[0];
if (Collection.class.isAssignableFrom(field.getType()))
{
try
{
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
if (subList != null && !subList.isEmpty())
{
maxSubListSize = Math.max(maxSubListSize, subList.size());
}
}
catch (Exception e)
{
log.error("获取集合大小失败", e);
} }
} }
} }
return maxSubListSize;
} }
/** /**
@@ -691,6 +726,7 @@ public class ExcelUtil<T>
style = wb.createCellStyle(); style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER); style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(dataFormat.getFormat("######0.00"));
Font totalFont = wb.createFont(); Font totalFont = wb.createFont();
totalFont.setFontName("Arial"); totalFont.setFontName("Arial");
totalFont.setFontHeightInPoints((short) 10); totalFont.setFontHeightInPoints((short) 10);
@@ -781,7 +817,7 @@ public class ExcelUtil<T>
*/ */
public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel) public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
{ {
String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType()); String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText());
if (!styles.containsKey(key)) if (!styles.containsKey(key))
{ {
CellStyle style = wb.createCellStyle(); CellStyle style = wb.createCellStyle();
@@ -797,6 +833,7 @@ public class ExcelUtil<T>
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND); style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(excel.backgroundColor().getIndex()); style.setFillForegroundColor(excel.backgroundColor().getIndex());
style.setWrapText(excel.wrapText());
Font dataFont = wb.createFont(); Font dataFont = wb.createFont();
dataFont.setFontName("Arial"); dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10); dataFont.setFontHeightInPoints((short) 10);
@@ -825,7 +862,7 @@ public class ExcelUtil<T>
if (isSubList()) if (isSubList())
{ {
// 填充默认样式,防止合并单元格样式失效 // 填充默认样式,防止合并单元格样式失效
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType()))); sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
if (attr.needMerge()) if (attr.needMerge())
{ {
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
@@ -950,12 +987,14 @@ public class ExcelUtil<T>
{ {
// 创建cell // 创建cell
cell = row.createCell(column); cell = row.createCell(column);
if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) if (isSubListValue(vo) && getListCellValue(vo) > 1 && attr.needMerge())
{ {
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column); if (subMergedLastRowNum >= subMergedFirstRowNum)
sheet.addMergedRegion(cellAddress); {
sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
}
} }
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType()))); cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
// 用于读取对象中的属性 // 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr); Object value = getTargetValue(vo, field, attr);
@@ -964,6 +1003,7 @@ public class ExcelUtil<T>
String separator = attr.separator(); String separator = attr.separator();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{ {
cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat));
cell.setCellValue(parseDateToStr(dateFormat, value)); cell.setCellValue(parseDateToStr(dateFormat, value));
} }
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
@@ -1044,18 +1084,36 @@ public class ExcelUtil<T>
public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
{ {
String hideSheetName = "combo_" + firstCol + "_" + endCol; String hideSheetName = "combo_" + firstCol + "_" + endCol;
Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 Sheet hideSheet = null;
for (int i = 0; i < textlist.length; i++) String hideSheetDataName = hideSheetName + "_data";
Name name = wb.getName(hideSheetDataName);
if (name != null)
{ {
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]); // 名称已存在尝试从名称的引用中找到sheet名称
String refersToFormula = name.getRefersToFormula();
if (StringUtils.isNotEmpty(refersToFormula) && refersToFormula.contains("!"))
{
String sheetNameFromFormula = refersToFormula.substring(0, refersToFormula.indexOf("!"));
hideSheet = wb.getSheet(sheetNameFromFormula);
}
} }
// 创建名称,可被其他单元格引用
Name name = wb.createName(); if (hideSheet == null)
name.setNameName(hideSheetName + "_data"); {
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length); hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据
for (int i = 0; i < textlist.length; i++)
{
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
}
// 创建名称,可被其他单元格引用
name = wb.createName();
name.setNameName(hideSheetDataName);
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
}
DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容 // 加载下拉列表内容
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data"); DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetDataName);
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象 // 数据有效性对象
@@ -1093,7 +1151,7 @@ public class ExcelUtil<T>
public static String convertByExp(String propertyValue, String converterExp, String separator) public static String convertByExp(String propertyValue, String converterExp, String separator)
{ {
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(","); String[] convertSource = converterExp.split(SEPARATOR);
for (String item : convertSource) for (String item : convertSource)
{ {
String[] itemArray = item.split("="); String[] itemArray = item.split("=");
@@ -1130,7 +1188,7 @@ public class ExcelUtil<T>
public static String reverseByExp(String propertyValue, String converterExp, String separator) public static String reverseByExp(String propertyValue, String converterExp, String separator)
{ {
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(","); String[] convertSource = converterExp.split(SEPARATOR);
for (String item : convertSource) for (String item : convertSource)
{ {
String[] itemArray = item.split("="); String[] itemArray = item.split("=");
@@ -1218,7 +1276,7 @@ public class ExcelUtil<T>
{ {
cell = row.createCell(key); cell = row.createCell(key);
cell.setCellStyle(styles.get("total")); cell.setCellStyle(styles.get("total"));
cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); cell.setCellValue(statistics.get(key));
} }
statistics.clear(); statistics.clear();
} }
@@ -1235,6 +1293,7 @@ public class ExcelUtil<T>
*/ */
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
{ {
field.setAccessible(true);
Object o = field.get(vo); Object o = field.get(vo);
if (StringUtils.isNotEmpty(excel.targetAttr())) if (StringUtils.isNotEmpty(excel.targetAttr()))
{ {
@@ -1292,6 +1351,8 @@ public class ExcelUtil<T>
{ {
List<Object[]> fields = new ArrayList<Object[]>(); List<Object[]> fields = new ArrayList<Object[]>();
List<Field> tempFields = new ArrayList<>(); List<Field> tempFields = new ArrayList<>();
subFieldsMap = new HashMap<>();
subMethods = new HashMap<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (StringUtils.isNotEmpty(includeFields)) if (StringUtils.isNotEmpty(includeFields))
@@ -1335,15 +1396,15 @@ public class ExcelUtil<T>
Excel attr = field.getAnnotation(Excel.class); Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{ {
field.setAccessible(true);
fields.add(new Object[] { field, attr }); fields.add(new Object[] { field, attr });
} }
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
subMethod = getSubMethod(field.getName(), clazz); String fieldName = field.getName();
subMethods.put(fieldName, getSubMethod(fieldName, clazz));
ParameterizedType pt = (ParameterizedType) field.getGenericType(); ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0]; Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); subFieldsMap.put(fieldName, FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class));
} }
} }
@@ -1359,7 +1420,6 @@ public class ExcelUtil<T>
if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr()) if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type))) && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{ {
field.setAccessible(true);
fields.add(new Object[] { field, attr }); fields.add(new Object[] { field, attr });
} }
} }
@@ -1368,7 +1428,6 @@ public class ExcelUtil<T>
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr()) if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type))) && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{ {
field.setAccessible(true);
fields.add(new Object[] { field, attr }); fields.add(new Object[] { field, attr });
} }
} }
@@ -1414,7 +1473,8 @@ public class ExcelUtil<T>
{ {
this.sheet = wb.createSheet(); this.sheet = wb.createSheet();
this.createTitle(); this.createTitle();
wb.setSheetName(index, sheetName + index); int actualIndex = wb.getSheetIndex(this.sheet);
wb.setSheetName(actualIndex, sheetName + index);
} }
} }
@@ -1539,7 +1599,7 @@ public class ExcelUtil<T>
*/ */
public boolean isSubList() public boolean isSubList()
{ {
return StringUtils.isNotNull(subFields) && subFields.size() > 0; return !StringUtils.isEmpty(subFieldsMap);
} }
/** /**
@@ -1547,24 +1607,32 @@ public class ExcelUtil<T>
*/ */
public boolean isSubListValue(T vo) public boolean isSubListValue(T vo)
{ {
return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0; return !StringUtils.isEmpty(subFieldsMap) && getListCellValue(vo) > 0;
} }
/** /**
* 获取集合的值 * 获取集合的值
*/ */
public Collection<?> getListCellValue(Object obj) public int getListCellValue(Object obj)
{ {
Object value; Collection<?> value;
int max = 0;
try try
{ {
value = subMethod.invoke(obj, new Object[] {}); for (String s : subMethods.keySet())
{
value = (Collection<?>) subMethods.get(s).invoke(obj);
if (value.size() > max)
{
max = value.size();
}
}
} }
catch (Exception e) catch (Exception e)
{ {
return new ArrayList<Object>(); return 0;
} }
return (Collection<?>) value; return max;
} }
/** /**

View File

@@ -13,7 +13,7 @@ public class SqlUtil
/** /**
* 定义常用的 sql关键字 * 定义常用的 sql关键字
*/ */
public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()"; public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
/** /**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)

View File

@@ -343,25 +343,25 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low // time_low
builder.append(digits(mostSigBits >> 32, 8)); builder.append(digits(mostSigBits >> 32, 8));
if (false == isSimple) if (!isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// time_mid // time_mid
builder.append(digits(mostSigBits >> 16, 4)); builder.append(digits(mostSigBits >> 16, 4));
if (false == isSimple) if (!isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// time_high_and_version // time_high_and_version
builder.append(digits(mostSigBits, 4)); builder.append(digits(mostSigBits, 4));
if (false == isSimple) if (!isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// variant_and_sequence // variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4)); builder.append(digits(leastSigBits >> 48, 4));
if (false == isSimple) if (!isSimple)
{ {
builder.append('-'); builder.append('-');
} }

View File

@@ -7,12 +7,17 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.constant.HttpStatus; import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.PageUtils; import com.ruoyi.common.core.utils.PageUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.sql.SqlUtil;
import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo; import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.core.web.page.TableSupport;
/** /**
* web层通用数据处理 * web层通用数据处理
@@ -48,6 +53,19 @@ public class BaseController
PageUtils.startPage(); PageUtils.startPage();
} }
/**
* 设置请求排序数据
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/** /**
* 清理分页的线程变量 * 清理分页的线程变量
*/ */

View File

@@ -37,7 +37,7 @@ public class TableDataInfo implements Serializable
* @param list 列表数据 * @param list 列表数据
* @param total 总记录数 * @param total 总记录数
*/ */
public TableDataInfo(List<?> list, int total) public TableDataInfo(List<?> list, long total)
{ {
this.rows = list; this.rows = list;
this.total = total; this.total = total;

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -94,7 +94,7 @@ public class DataScopeAspect
List<String> conditions = new ArrayList<String>(); List<String> conditions = new ArrayList<String>();
List<String> scopeCustomIds = new ArrayList<String>(); List<String> scopeCustomIds = new ArrayList<String>();
user.getRoles().forEach(role -> { user.getRoles().forEach(role -> {
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && (StringUtils.isEmpty(permission) || StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))))
{ {
scopeCustomIds.add(Convert.toStr(role.getRoleId())); scopeCustomIds.add(Convert.toStr(role.getRoleId()));
} }
@@ -107,7 +107,7 @@ public class DataScopeAspect
{ {
continue; continue;
} }
if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) if (StringUtils.isNotEmpty(permission) && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{ {
continue; continue;
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -19,6 +19,8 @@ import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.ExceptionUtil;
import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils; import com.ruoyi.common.core.utils.ip.IpUtils;
@@ -46,6 +48,9 @@ public class LogAspect
/** 计算操作消耗时间 */ /** 计算操作消耗时间 */
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time"); private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
/** 参数最大长度限制 */
private static final int PARAM_MAX_LENGTH = 2000;
@Autowired @Autowired
private AsyncLogService asyncLogService; private AsyncLogService asyncLogService;
@@ -53,7 +58,7 @@ public class LogAspect
* 处理请求前执行 * 处理请求前执行
*/ */
@Before(value = "@annotation(controllerLog)") @Before(value = "@annotation(controllerLog)")
public void boBefore(JoinPoint joinPoint, Log controllerLog) public void doBefore(JoinPoint joinPoint, Log controllerLog)
{ {
TIME_THREADLOCAL.set(System.currentTimeMillis()); TIME_THREADLOCAL.set(System.currentTimeMillis());
} }
@@ -101,7 +106,7 @@ public class LogAspect
if (e != null) if (e != null)
{ {
operLog.setStatus(BusinessStatus.FAIL.ordinal()); operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); operLog.setErrorMsg(StringUtils.substring(Convert.toStr(e.getMessage(), ExceptionUtil.getExceptionMessage(e)), 0, 2000));
} }
// 设置方法名称 // 设置方法名称
String className = joinPoint.getTarget().getClass().getName(); String className = joinPoint.getTarget().getClass().getName();
@@ -164,16 +169,16 @@ public class LogAspect
*/ */
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
{ {
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
String requestMethod = operLog.getRequestMethod(); String requestMethod = operLog.getRequestMethod();
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())) if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
{ {
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
operLog.setOperParam(StringUtils.substring(params, 0, 2000)); operLog.setOperParam(params);
} }
else else
{ {
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000)); operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, PARAM_MAX_LENGTH));
} }
} }
@@ -182,7 +187,7 @@ public class LogAspect
*/ */
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
{ {
String params = ""; StringBuilder params = new StringBuilder();
if (paramsArray != null && paramsArray.length > 0) if (paramsArray != null && paramsArray.length > 0)
{ {
for (Object o : paramsArray) for (Object o : paramsArray)
@@ -192,15 +197,20 @@ public class LogAspect
try try
{ {
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames)); String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
params += jsonObj.toString() + " "; params.append(jsonObj).append(" ");
if (params.length() >= PARAM_MAX_LENGTH)
{
return StringUtils.substring(params.toString(), 0, PARAM_MAX_LENGTH);
}
} }
catch (Exception e) catch (Exception e)
{ {
log.error("请求参数拼装异常 msg:{}, 参数:{}", e.getMessage(), paramsArray, e);
} }
} }
} }
} }
return params.trim(); return params.toString();
} }
/** /**

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -56,16 +56,8 @@ public class PreAuthorizeAspect
// 注解鉴权 // 注解鉴权
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
checkMethodAnnotation(signature.getMethod()); checkMethodAnnotation(signature.getMethod());
try // 执行原有逻辑
{ return joinPoint.proceed();
// 执行原有逻辑
Object obj = joinPoint.proceed();
return obj;
}
catch (Throwable e)
{
throw e;
}
} }
/** /**

View File

@@ -36,11 +36,11 @@ public class TokenService
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private final static long expireTime = CacheConstants.EXPIRATION; private final static long TOKEN_EXPIRE_TIME = CacheConstants.EXPIRATION;
private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY; private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE; private final static Long TOKEN_REFRESH_THRESHOLD_MINUTES = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
/** /**
* 创建令牌 * 创建令牌
@@ -65,7 +65,7 @@ public class TokenService
// 接口返回信息 // 接口返回信息
Map<String, Object> rspMap = new HashMap<String, Object>(); Map<String, Object> rspMap = new HashMap<String, Object>();
rspMap.put("access_token", JwtUtils.createToken(claimsMap)); rspMap.put("access_token", JwtUtils.createToken(claimsMap));
rspMap.put("expires_in", expireTime); rspMap.put("expires_in", TOKEN_EXPIRE_TIME);
return rspMap; return rspMap;
} }
@@ -147,7 +147,7 @@ public class TokenService
{ {
long expireTime = loginUser.getExpireTime(); long expireTime = loginUser.getExpireTime();
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN) if (expireTime - currentTime <= TOKEN_REFRESH_THRESHOLD_MINUTES)
{ {
refreshToken(loginUser); refreshToken(loginUser);
} }
@@ -161,10 +161,10 @@ public class TokenService
public void refreshToken(LoginUser loginUser) public void refreshToken(LoginUser loginUser)
{ {
loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); loginUser.setExpireTime(loginUser.getLoginTime() + TOKEN_EXPIRE_TIME * MILLIS_MINUTE);
// 根据uuid将loginUser缓存 // 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken()); String userKey = getTokenKey(loginUser.getToken());
redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); redisService.setCacheObject(userKey, loginUser, TOKEN_EXPIRE_TIME, TimeUnit.MINUTES);
} }
private String getTokenKey(String token) private String getTokenKey(String token)

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -17,10 +17,10 @@
<dependencies> <dependencies>
<!-- RuoYi Common Security --> <!-- RuoYi Common Core -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId> <artifactId>ruoyi-common-core</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -8,10 +8,10 @@ import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.sensitive.annotation.Sensitive; import com.ruoyi.common.sensitive.annotation.Sensitive;
import com.ruoyi.common.sensitive.enums.DesensitizedType; import com.ruoyi.common.sensitive.enums.DesensitizedType;
import com.ruoyi.system.api.model.LoginUser;
/** /**
* 数据脱敏序列化过滤 * 数据脱敏序列化过滤
@@ -55,9 +55,9 @@ public class SensitiveJsonSerializer extends JsonSerializer<String> implements C
{ {
try try
{ {
LoginUser securityUser = SecurityUtils.getLoginUser(); Long userId = SecurityContextHolder.getUserId();
// 管理员不脱敏 // 管理员不脱敏
return !securityUser.getSysUser().isAdmin(); return !UserConstants.isAdmin(userId);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1,87 +0,0 @@
package com.ruoyi.gateway.filter;
import java.util.Collections;
import java.util.List;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 获取body请求数据解决流不能重复读取问题
*
* @author ruoyi
*/
@Component
public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config>
{
public CacheRequestFilter()
{
super(Config.class);
}
@Override
public String name()
{
return "CacheRequestFilter";
}
@Override
public GatewayFilter apply(Config config)
{
CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter();
Integer order = config.getOrder();
if (order == null)
{
return cacheRequestGatewayFilter;
}
return new OrderedGatewayFilter(cacheRequestGatewayFilter, order);
}
public static class CacheRequestGatewayFilter implements GatewayFilter
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
// GET DELETE 不过滤
HttpMethod method = exchange.getRequest().getMethod();
if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE)
{
return chain.filter(exchange);
}
return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {
if (serverHttpRequest == exchange.getRequest())
{
return chain.filter(exchange);
}
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
});
}
}
@Override
public List<String> shortcutFieldOrder()
{
return Collections.singletonList("order");
}
static class Config
{
private Integer order;
public Integer getOrder()
{
return order;
}
public void setOrder(Integer order)
{
this.order = order;
}
}
}

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,46 @@
package com.ruoyi.file.config;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.file.filter.RefererFilter;
/**
* Filter配置
*
* @author ruoyi
*/
@Configuration
public class FilterConfig
{
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
@Value("${referer.allowed-domains}")
private String allowedDomains;
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(value = "referer.enabled", havingValue = "true")
public FilterRegistrationBean refererFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new RefererFilter());
registration.addUrlPatterns(localFilePrefix + "/*");
registration.setName("refererFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("allowedDomains", allowedDomains);
registration.setInitParameters(initParameters);
return registration;
}
}

View File

@@ -3,10 +3,12 @@ package com.ruoyi.file.controller;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileUtils; import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService; import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile; import com.ruoyi.system.api.domain.SysFile;
@@ -45,4 +47,26 @@ public class SysFileController
return R.fail(e.getMessage()); return R.fail(e.getMessage());
} }
} }
}
/**
* 文件删除请求
*/
@DeleteMapping("delete")
public R<Boolean> delete(String fileUrl)
{
try
{
if (!FileUtils.validateFilePath(fileUrl))
{
throw new Exception(StringUtils.format("资源文件({})非法,不允许删除。 ", fileUrl));
}
sysFileService.deleteFile(fileUrl);
return R.ok();
}
catch (Exception e)
{
log.error("删除文件失败", e);
return R.fail(e.getMessage());
}
}
}

View File

@@ -0,0 +1,77 @@
package com.ruoyi.file.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 防盗链过滤器
*
* @author ruoyi
*/
public class RefererFilter implements Filter
{
/**
* 允许的域名列表
*/
public List<String> allowedDomains;
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String domains = filterConfig.getInitParameter("allowedDomains");
this.allowedDomains = Arrays.asList(domains.split(","));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String referer = req.getHeader("Referer");
// 如果Referer为空拒绝访问
if (referer == null || referer.isEmpty())
{
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required");
return;
}
// 检查Referer是否在允许的域名列表中
boolean allowed = false;
for (String domain : allowedDomains)
{
if (referer.contains(domain))
{
allowed = true;
break;
}
}
// 根据检查结果决定是否放行
if (allowed)
{
chain.doFilter(request, response);
}
else
{
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed");
}
}
@Override
public void destroy()
{
}
}

View File

@@ -1,11 +1,11 @@
package com.ruoyi.file.service; package com.ruoyi.file.service;
import java.io.InputStream; import java.io.InputStream;
import com.alibaba.nacos.common.utils.IoUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils;
import com.github.tobato.fastdfs.domain.fdfs.StorePath; import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient; import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.common.core.utils.file.FileTypeUtils; import com.ruoyi.common.core.utils.file.FileTypeUtils;
@@ -37,10 +37,40 @@ public class FastDfsSysFileServiceImpl implements ISysFileService
@Override @Override
public String uploadFile(MultipartFile file) throws Exception public String uploadFile(MultipartFile file) throws Exception
{ {
InputStream inputStream = file.getInputStream(); InputStream inputStream = null;
StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(), try
FileTypeUtils.getExtension(file), null); {
IoUtils.closeQuietly(inputStream); inputStream = file.getInputStream();
return domain + "/" + storePath.getFullPath(); StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(), FileTypeUtils.getExtension(file), null);
return domain + "/" + storePath.getFullPath();
}
catch (Exception e)
{
throw new RuntimeException("FastDfs Failed to upload file", e);
}
finally
{
IoUtils.closeQuietly(inputStream);
}
}
/**
* FastDFS文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
try
{
StorePath storePath = StorePath.parseFromUrl(fileUrl);
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
}
catch (Exception e)
{
throw new RuntimeException("FastDfs Failed to delete file: ", e);
}
} }
} }

View File

@@ -17,4 +17,12 @@ public interface ISysFileService
* @throws Exception * @throws Exception
*/ */
public String uploadFile(MultipartFile file) throws Exception; public String uploadFile(MultipartFile file) throws Exception;
/**
* 文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
public void deleteFile(String fileUrl) throws Exception;
} }

View File

@@ -4,6 +4,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.utils.FileUploadUtils; import com.ruoyi.file.utils.FileUploadUtils;
/** /**
@@ -47,4 +49,17 @@ public class LocalSysFileServiceImpl implements ISysFileService
String url = domain + localFilePrefix + name; String url = domain + localFilePrefix + name;
return url; return url;
} }
/**
* 本地文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
String localFile = StringUtils.substringAfter(fileUrl, localFilePrefix);
FileUtils.deleteFile(localFilePath + localFile);
}
} }

View File

@@ -5,10 +5,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils; import com.alibaba.nacos.common.utils.IoUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.file.config.MinioConfig; import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.utils.FileUploadUtils; import com.ruoyi.file.utils.FileUploadUtils;
import io.minio.MinioClient; import io.minio.MinioClient;
import io.minio.PutObjectArgs; import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
/** /**
* Minio 文件存储 * Minio 文件存储
@@ -34,16 +36,47 @@ public class MinioSysFileServiceImpl implements ISysFileService
@Override @Override
public String uploadFile(MultipartFile file) throws Exception public String uploadFile(MultipartFile file) throws Exception
{ {
String fileName = FileUploadUtils.extractFilename(file); InputStream inputStream = null;
InputStream inputStream = file.getInputStream(); try
PutObjectArgs args = PutObjectArgs.builder() {
.bucket(minioConfig.getBucketName()) String fileName = FileUploadUtils.extractFilename(file);
.object(fileName) inputStream = file.getInputStream();
.stream(inputStream, file.getSize(), -1) PutObjectArgs args = PutObjectArgs.builder()
.contentType(file.getContentType()) .bucket(minioConfig.getBucketName())
.build(); .object(fileName)
client.putObject(args); .stream(inputStream, file.getSize(), -1)
IoUtils.closeQuietly(inputStream); .contentType(file.getContentType())
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName; .build();
client.putObject(args);
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
}
catch (Exception e)
{
throw new RuntimeException("Minio Failed to upload file", e);
}
finally
{
IoUtils.closeQuietly(inputStream);
}
}
/**
* Minio文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
try
{
String minioFile = StringUtils.substringAfter(fileUrl, minioConfig.getBucketName());
client.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(minioFile).build());
}
catch (Exception e)
{
throw new RuntimeException("Minio Failed to delete file", e);
}
} }
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -18,12 +18,15 @@ public class GenConfig
/** 生成包路径 */ /** 生成包路径 */
public static String packageName; public static String packageName;
/** 自动去除表前缀默认是false */ /** 自动去除表前缀 */
public static boolean autoRemovePre; public static boolean autoRemovePre;
/** 表前缀(类名不会包含表前缀) */ /** 表前缀 */
public static String tablePrefix; public static String tablePrefix;
/** 是否允许生成文件覆盖到本地(自定义路径) */
public static boolean allowOverwrite;
public static String getAuthor() public static String getAuthor()
{ {
return author; return author;
@@ -63,4 +66,14 @@ public class GenConfig
{ {
GenConfig.tablePrefix = tablePrefix; GenConfig.tablePrefix = tablePrefix;
} }
public static boolean isAllowOverwrite()
{
return allowOverwrite;
}
public void setAllowOverwrite(boolean allowOverwrite)
{
GenConfig.allowOverwrite = allowOverwrite;
}
} }

View File

@@ -23,6 +23,7 @@ import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.gen.config.GenConfig;
import com.ruoyi.gen.domain.GenTable; import com.ruoyi.gen.domain.GenTable;
import com.ruoyi.gen.domain.GenTableColumn; import com.ruoyi.gen.domain.GenTableColumn;
import com.ruoyi.gen.service.IGenTableColumnService; import com.ruoyi.gen.service.IGenTableColumnService;
@@ -56,7 +57,7 @@ public class GenController extends BaseController
} }
/** /**
* 修改代码生成业务 * 获取代码生成信息
*/ */
@RequiresPermissions("tool:gen:query") @RequiresPermissions("tool:gen:query")
@GetMapping(value = "/{tableId}") @GetMapping(value = "/{tableId}")
@@ -168,6 +169,10 @@ public class GenController extends BaseController
@GetMapping("/genCode/{tableName}") @GetMapping("/genCode/{tableName}")
public AjaxResult genCode(@PathVariable("tableName") String tableName) public AjaxResult genCode(@PathVariable("tableName") String tableName)
{ {
if (!GenConfig.isAllowOverwrite())
{
return AjaxResult.error("【系统预设】不允许生成文件覆盖到本地");
}
genTableService.generatorCode(tableName); genTableService.generatorCode(tableName);
return success(); return success();
} }

View File

@@ -129,9 +129,9 @@ public class GenTableServiceImpl implements IGenTableService
int row = genTableMapper.updateGenTable(genTable); int row = genTableMapper.updateGenTable(genTable);
if (row > 0) if (row > 0)
{ {
for (GenTableColumn cenTableColumn : genTable.getColumns()) for (GenTableColumn genTableColumn : genTable.getColumns())
{ {
genTableColumnMapper.updateGenTableColumn(cenTableColumn); genTableColumnMapper.updateGenTableColumn(genTableColumn);
} }
} }
} }
@@ -414,16 +414,16 @@ public class GenTableServiceImpl implements IGenTableService
{ {
throw new ServiceException("树名称字段不能为空"); throw new ServiceException("树名称字段不能为空");
} }
else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory())) }
else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
{
if (StringUtils.isEmpty(genTable.getSubTableName()))
{ {
if (StringUtils.isEmpty(genTable.getSubTableName())) throw new ServiceException("关联子表的表名不能为空");
{ }
throw new ServiceException("关联子表的表名不能为空"); else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
} {
else if (StringUtils.isEmpty(genTable.getSubTableFkName())) throw new ServiceException("子表关联的外键名不能为空");
{
throw new ServiceException("子表关联的外键名不能为空");
}
} }
} }
} }

View File

@@ -71,9 +71,9 @@ public class ${ClassName} extends ${Entity}
{ {
return $column.javaField; return $column.javaField;
} }
#end
#end
#end
#end
#if($table.sub) #if($table.sub)
public List<${subClassName}> get${subClassName}List() public List<${subClassName}> get${subClassName}List()
{ {

View File

@@ -75,7 +75,7 @@
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${moduleName}:${businessName}:add']" v-hasPermi="['${permissionPrefix}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -144,21 +144,21 @@
type="text" type="text"
icon="el-icon-edit" icon="el-icon-edit"
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:edit']" v-hasPermi="['${permissionPrefix}:edit']"
>修改</el-button> >修改</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-plus" icon="el-icon-plus"
@click="handleAdd(scope.row)" @click="handleAdd(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:add']" v-hasPermi="['${permissionPrefix}:add']"
>新增</el-button> >新增</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:remove']" v-hasPermi="['${permissionPrefix}:remove']"
>删除</el-button> >删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
@@ -283,9 +283,9 @@
</template> </template>
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
import Treeselect from "@riophae/vue-treeselect"; import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css"
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@@ -346,18 +346,18 @@ export default {
#end #end
#end #end
} }
}; }
}, },
created() { created() {
this.getList(); this.getList()
}, },
methods: { methods: {
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
getList() { getList() {
this.loading = true; this.loading = true
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
this.queryParams.params = {}; this.queryParams.params = {}
#break #break
#end #end
#end #end
@@ -365,40 +365,40 @@ export default {
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) { if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]; this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]; this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]
} }
#end #end
#end #end
list${BusinessName}(this.queryParams).then(response => { list${BusinessName}(this.queryParams).then(response => {
this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}"); this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}")
this.loading = false; this.loading = false
}); })
}, },
/** 转换${functionName}数据结构 */ /** 转换${functionName}数据结构 */
normalizer(node) { normalizer(node) {
if (node.children && !node.children.length) { if (node.children && !node.children.length) {
delete node.children; delete node.children
} }
return { return {
id: node.${treeCode}, id: node.${treeCode},
label: node.${treeName}, label: node.${treeName},
children: node.children children: node.children
}; }
}, },
/** 查询${functionName}下拉树结构 */ /** 查询${functionName}下拉树结构 */
getTreeselect() { getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
this.${businessName}Options = []; this.${businessName}Options = []
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }; const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}"); data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}")
this.${businessName}Options.push(data); this.${businessName}Options.push(data)
}); })
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false; this.open = false
this.reset(); this.reset()
}, },
// 表单重置 // 表单重置
reset() { reset() {
@@ -410,61 +410,61 @@ export default {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
}; }
this.resetForm("form"); this.resetForm("form")
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.getList(); this.getList()
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.daterange${AttrName} = []; this.daterange${AttrName} = []
#end #end
#end #end
this.resetForm("queryForm"); this.resetForm("queryForm")
this.handleQuery(); this.handleQuery()
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd(row) { handleAdd(row) {
this.reset(); this.reset()
this.getTreeselect(); this.getTreeselect()
if (row != null && row.${treeCode}) { if (row != null && row.${treeCode}) {
this.form.${treeParentCode} = row.${treeCode}; this.form.${treeParentCode} = row.${treeCode}
} else { } else {
this.form.${treeParentCode} = 0; this.form.${treeParentCode} = 0
} }
this.open = true; this.open = true
this.title = "添加${functionName}"; this.title = "添加${functionName}"
}, },
/** 展开/折叠操作 */ /** 展开/折叠操作 */
toggleExpandAll() { toggleExpandAll() {
this.refreshTable = false; this.refreshTable = false
this.isExpandAll = !this.isExpandAll; this.isExpandAll = !this.isExpandAll
this.$nextTick(() => { this.$nextTick(() => {
this.refreshTable = true; this.refreshTable = true
}); })
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset()
this.getTreeselect(); this.getTreeselect()
if (row != null) { if (row != null) {
this.form.${treeParentCode} = row.${treeCode}; this.form.${treeParentCode} = row.${treeParentCode}
} }
get${BusinessName}(row.${pkColumn.javaField}).then(response => { get${BusinessName}(row.${pkColumn.javaField}).then(response => {
this.form = response.data; this.form = response.data
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(","); this.form.$column.javaField = this.form.${column.javaField}.split(",")
#end #end
#end #end
this.open = true; this.open = true
this.title = "修改${functionName}"; this.title = "修改${functionName}"
}); })
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
@@ -472,34 +472,34 @@ export default {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(","); this.form.$column.javaField = this.form.${column.javaField}.join(",")
#end #end
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("修改成功"); this.#[[$modal]]#.msgSuccess("修改成功")
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功"); this.#[[$modal]]#.msgSuccess("新增成功")
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} }
} }
}); })
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() { this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField}); return del${BusinessName}(row.${pkColumn.javaField})
}).then(() => { }).then(() => {
this.getList(); this.getList()
this.#[[$modal]]#.msgSuccess("删除成功"); this.#[[$modal]]#.msgSuccess("删除成功")
}).catch(() => {}); }).catch(() => {})
} }
} }
}; }
</script> </script>

View File

@@ -75,7 +75,7 @@
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${moduleName}:${businessName}:add']" v-hasPermi="['${permissionPrefix}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -86,7 +86,7 @@
size="mini" size="mini"
:disabled="single" :disabled="single"
@click="handleUpdate" @click="handleUpdate"
v-hasPermi="['${moduleName}:${businessName}:edit']" v-hasPermi="['${permissionPrefix}:edit']"
>修改</el-button> >修改</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -97,7 +97,7 @@
size="mini" size="mini"
:disabled="multiple" :disabled="multiple"
@click="handleDelete" @click="handleDelete"
v-hasPermi="['${moduleName}:${businessName}:remove']" v-hasPermi="['${permissionPrefix}:remove']"
>删除</el-button> >删除</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -107,7 +107,7 @@
icon="el-icon-download" icon="el-icon-download"
size="mini" size="mini"
@click="handleExport" @click="handleExport"
v-hasPermi="['${moduleName}:${businessName}:export']" v-hasPermi="['${permissionPrefix}:export']"
>导出</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>
@@ -158,14 +158,14 @@
type="text" type="text"
icon="el-icon-edit" icon="el-icon-edit"
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:edit']" v-hasPermi="['${permissionPrefix}:edit']"
>修改</el-button> >修改</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:remove']" v-hasPermi="['${permissionPrefix}:remove']"
>删除</el-button> >删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
@@ -353,7 +353,7 @@
</template> </template>
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@@ -423,18 +423,18 @@ export default {
#end #end
#end #end
} }
}; }
}, },
created() { created() {
this.getList(); this.getList()
}, },
methods: { methods: {
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
getList() { getList() {
this.loading = true; this.loading = true
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
this.queryParams.params = {}; this.queryParams.params = {}
#break #break
#end #end
#end #end
@@ -442,21 +442,21 @@ export default {
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) { if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]; this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0]
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]; this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1]
} }
#end #end
#end #end
list${BusinessName}(this.queryParams).then(response => { list${BusinessName}(this.queryParams).then(response => {
this.${businessName}List = response.rows; this.${businessName}List = response.rows
this.total = response.total; this.total = response.total
this.loading = false; this.loading = false
}); })
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false; this.open = false
this.reset(); this.reset()
}, },
// 表单重置 // 表单重置
reset() { reset() {
@@ -468,27 +468,27 @@ export default {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
}; }
#if($table.sub) #if($table.sub)
this.${subclassName}List = []; this.${subclassName}List = []
#end #end
this.resetForm("form"); this.resetForm("form")
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1
this.getList(); this.getList()
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.daterange${AttrName} = []; this.daterange${AttrName} = []
#end #end
#end #end
this.resetForm("queryForm"); this.resetForm("queryForm")
this.handleQuery(); this.handleQuery()
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
@@ -498,27 +498,27 @@ export default {
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset(); this.reset()
this.open = true; this.open = true
this.title = "添加${functionName}"; this.title = "添加${functionName}"
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset()
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
get${BusinessName}(${pkColumn.javaField}).then(response => { get${BusinessName}(${pkColumn.javaField}).then(response => {
this.form = response.data; this.form = response.data
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(","); this.form.$column.javaField = this.form.${column.javaField}.split(",")
#end #end
#end #end
#if($table.sub) #if($table.sub)
this.${subclassName}List = response.data.${subclassName}List; this.${subclassName}List = response.data.${subclassName}List
#end #end
this.open = true; this.open = true
this.title = "修改${functionName}"; this.title = "修改${functionName}"
}); })
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
@@ -526,64 +526,64 @@ export default {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(","); this.form.$column.javaField = this.form.${column.javaField}.join(",")
#end #end
#end #end
#if($table.sub) #if($table.sub)
this.form.${subclassName}List = this.${subclassName}List; this.form.${subclassName}List = this.${subclassName}List
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("修改成功"); this.#[[$modal]]#.msgSuccess("修改成功")
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功"); this.#[[$modal]]#.msgSuccess("新增成功")
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} }
} }
}); })
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids; const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() { this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(${pkColumn.javaField}s); return del${BusinessName}(${pkColumn.javaField}s)
}).then(() => { }).then(() => {
this.getList(); this.getList()
this.#[[$modal]]#.msgSuccess("删除成功"); this.#[[$modal]]#.msgSuccess("删除成功")
}).catch(() => {}); }).catch(() => {})
}, },
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
row${subClassName}Index({ row, rowIndex }) { row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1; row.index = rowIndex + 1
}, },
/** ${subTable.functionName}添加按钮操作 */ /** ${subTable.functionName}添加按钮操作 */
handleAdd${subClassName}() { handleAdd${subClassName}() {
let obj = {}; let obj = {}
#foreach($column in $subTable.columns) #foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName}) #if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
obj.$column.javaField = ""; obj.$column.javaField = ""
#end #end
#end #end
this.${subclassName}List.push(obj); this.${subclassName}List.push(obj)
}, },
/** ${subTable.functionName}删除按钮操作 */ /** ${subTable.functionName}删除按钮操作 */
handleDelete${subClassName}() { handleDelete${subClassName}() {
if (this.checked${subClassName}.length == 0) { if (this.checked${subClassName}.length == 0) {
this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据"); this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
} else { } else {
const ${subclassName}List = this.${subclassName}List; const ${subclassName}List = this.${subclassName}List
const checked${subClassName} = this.checked${subClassName}; const checked${subClassName} = this.checked${subClassName}
this.${subclassName}List = ${subclassName}List.filter(function(item) { this.${subclassName}List = ${subclassName}List.filter(function(item) {
return checked${subClassName}.indexOf(item.index) == -1 return checked${subClassName}.indexOf(item.index) == -1
}); })
} }
}, },
/** 复选框选中数据 */ /** 复选框选中数据 */
@@ -598,5 +598,5 @@ export default {
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
} }
} }
}; }
</script> </script>

View File

@@ -73,7 +73,7 @@
plain plain
icon="Plus" icon="Plus"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${moduleName}:${businessName}:add']" v-hasPermi="['${permissionPrefix}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -136,9 +136,9 @@
#end #end
<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 #default="scope"> <template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button>
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button> <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${permissionPrefix}:add']">新增</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button> <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -271,26 +271,26 @@
</template> </template>
<script setup name="${BusinessName}"> <script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance()
#if(${dicts} != '') #if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", "")) #set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts}); const { ${dictsNoSymbol} } = proxy.useDict(${dicts})
#end #end
const ${businessName}List = ref([]); const ${businessName}List = ref([])
const ${businessName}Options = ref([]); const ${businessName}Options = ref([])
const open = ref(false); const open = ref(false)
const loading = ref(true); const loading = ref(true)
const showSearch = ref(true); const showSearch = ref(true)
const title = ref(""); const title = ref("")
const isExpandAll = ref(true); const isExpandAll = ref(true)
const refreshTable = ref(true); const refreshTable = ref(true)
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]); const daterange${AttrName} = ref([])
#end #end
#end #end
@@ -318,48 +318,48 @@ const data = reactive({
#end #end
#end #end
} }
}); })
const { queryParams, form, rules } = toRefs(data); const { queryParams, form, rules } = toRefs(data)
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
function getList() { function getList() {
loading.value = true; loading.value = true
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {}; queryParams.value.params = {}
#break #break
#end #end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName} && '' != daterange${AttrName}) { if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]; queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]; queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
} }
#end #end
#end #end
list${BusinessName}(queryParams.value).then(response => { list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}"); ${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
loading.value = false; loading.value = false
}); })
} }
/** 查询${functionName}下拉树结构 */ /** 查询${functionName}下拉树结构 */
function getTreeselect() { function getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
${businessName}Options.value = []; ${businessName}Options.value = []
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }; const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] }
data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}"); data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}")
${businessName}Options.value.push(data); ${businessName}Options.value.push(data)
}); })
} }
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false; open.value = false
reset(); reset()
} }
// 表单重置 // 表单重置
@@ -372,13 +372,13 @@ function reset() {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
}; }
proxy.resetForm("${businessName}Ref"); proxy.resetForm("${businessName}Ref")
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
getList(); getList()
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
@@ -386,52 +386,52 @@ function resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = []; daterange${AttrName}.value = []
#end #end
#end #end
proxy.resetForm("queryRef"); proxy.resetForm("queryRef")
handleQuery(); handleQuery()
} }
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd(row) { function handleAdd(row) {
reset(); reset()
getTreeselect(); getTreeselect()
if (row != null && row.${treeCode}) { if (row != null && row.${treeCode}) {
form.value.${treeParentCode} = row.${treeCode}; form.value.${treeParentCode} = row.${treeCode}
} else { } else {
form.value.${treeParentCode} = 0; form.value.${treeParentCode} = 0
} }
open.value = true; open.value = true
title.value = "添加${functionName}"; title.value = "添加${functionName}"
} }
/** 展开/折叠操作 */ /** 展开/折叠操作 */
function toggleExpandAll() { function toggleExpandAll() {
refreshTable.value = false; refreshTable.value = false
isExpandAll.value = !isExpandAll.value; isExpandAll.value = !isExpandAll.value
nextTick(() => { nextTick(() => {
refreshTable.value = true; refreshTable.value = true
}); })
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
async function handleUpdate(row) { async function handleUpdate(row) {
reset(); reset()
await getTreeselect(); await getTreeselect()
if (row != null) { if (row != null) {
form.value.${treeParentCode} = row.${treeCode}; form.value.${treeParentCode} = row.${treeParentCode}
} }
get${BusinessName}(row.${pkColumn.javaField}).then(response => { get${BusinessName}(row.${pkColumn.javaField}).then(response => {
form.value = response.data; form.value = response.data
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(","); form.value.$column.javaField = form.value.${column.javaField}.split(",")
#end #end
#end #end
open.value = true; open.value = true
title.value = "修改${functionName}"; title.value = "修改${functionName}"
}); })
} }
/** 提交按钮 */ /** 提交按钮 */
@@ -440,35 +440,35 @@ function submitForm() {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(","); form.value.$column.javaField = form.value.${column.javaField}.join(",")
#end #end
#end #end
if (form.value.${pkColumn.javaField} != null) { if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => { update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功"); proxy.#[[$modal]]#.msgSuccess("修改成功")
open.value = false; open.value = false
getList(); getList()
}); })
} else { } else {
add${BusinessName}(form.value).then(response => { add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功"); proxy.#[[$modal]]#.msgSuccess("新增成功")
open.value = false; open.value = false
getList(); getList()
}); })
} }
} }
}); })
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
function handleDelete(row) { function handleDelete(row) {
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() { proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField}); return del${BusinessName}(row.${pkColumn.javaField})
}).then(() => { }).then(() => {
getList(); getList()
proxy.#[[$modal]]#.msgSuccess("删除成功"); proxy.#[[$modal]]#.msgSuccess("删除成功")
}).catch(() => {}); }).catch(() => {})
} }
getList(); getList()
</script> </script>

View File

@@ -73,7 +73,7 @@
plain plain
icon="Plus" icon="Plus"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${moduleName}:${businessName}:add']" v-hasPermi="['${permissionPrefix}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -83,7 +83,7 @@
icon="Edit" icon="Edit"
:disabled="single" :disabled="single"
@click="handleUpdate" @click="handleUpdate"
v-hasPermi="['${moduleName}:${businessName}:edit']" v-hasPermi="['${permissionPrefix}:edit']"
>修改</el-button> >修改</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -93,7 +93,7 @@
icon="Delete" icon="Delete"
:disabled="multiple" :disabled="multiple"
@click="handleDelete" @click="handleDelete"
v-hasPermi="['${moduleName}:${businessName}:remove']" v-hasPermi="['${permissionPrefix}:remove']"
>删除</el-button> >删除</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -102,7 +102,7 @@
plain plain
icon="Download" icon="Download"
@click="handleExport" @click="handleExport"
v-hasPermi="['${moduleName}:${businessName}:export']" v-hasPermi="['${permissionPrefix}:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
@@ -148,8 +148,8 @@
#end #end
<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 #default="scope"> <template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button> <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -343,33 +343,33 @@
</template> </template>
<script setup name="${BusinessName}"> <script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance()
#if(${dicts} != '') #if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", "")) #set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts}); const { ${dictsNoSymbol} } = proxy.useDict(${dicts})
#end #end
const ${businessName}List = ref([]); const ${businessName}List = ref([])
#if($table.sub) #if($table.sub)
const ${subclassName}List = ref([]); const ${subclassName}List = ref([])
#end #end
const open = ref(false); const open = ref(false)
const loading = ref(true); const loading = ref(true)
const showSearch = ref(true); const showSearch = ref(true)
const ids = ref([]); const ids = ref([])
#if($table.sub) #if($table.sub)
const checked${subClassName} = ref([]); const checked${subClassName} = ref([])
#end #end
const single = ref(true); const single = ref(true)
const multiple = ref(true); const multiple = ref(true)
const total = ref(0); const total = ref(0)
const title = ref(""); const title = ref("")
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]); const daterange${AttrName} = ref([])
#end #end
#end #end
@@ -399,39 +399,39 @@ const data = reactive({
#end #end
#end #end
} }
}); })
const { queryParams, form, rules } = toRefs(data); const { queryParams, form, rules } = toRefs(data)
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
function getList() { function getList() {
loading.value = true; loading.value = true
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {}; queryParams.value.params = {}
#break #break
#end #end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName} && '' != daterange${AttrName}) { if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]; queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0]
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]; queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1]
} }
#end #end
#end #end
list${BusinessName}(queryParams.value).then(response => { list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = response.rows; ${businessName}List.value = response.rows
total.value = response.total; total.value = response.total
loading.value = false; loading.value = false
}); })
} }
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false; open.value = false
reset(); reset()
} }
// 表单重置 // 表单重置
@@ -444,17 +444,17 @@ function reset() {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
}; }
#if($table.sub) #if($table.sub)
${subclassName}List.value = []; ${subclassName}List.value = []
#end #end
proxy.resetForm("${businessName}Ref"); proxy.resetForm("${businessName}Ref")
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
queryParams.value.pageNum = 1; queryParams.value.pageNum = 1
getList(); getList()
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
@@ -462,44 +462,44 @@ function resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = []; daterange${AttrName}.value = []
#end #end
#end #end
proxy.resetForm("queryRef"); proxy.resetForm("queryRef")
handleQuery(); handleQuery()
} }
// 多选框选中数据 // 多选框选中数据
function handleSelectionChange(selection) { function handleSelectionChange(selection) {
ids.value = selection.map(item => item.${pkColumn.javaField}); ids.value = selection.map(item => item.${pkColumn.javaField})
single.value = selection.length != 1; single.value = selection.length != 1
multiple.value = !selection.length; multiple.value = !selection.length
} }
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd() { function handleAdd() {
reset(); reset()
open.value = true; open.value = true
title.value = "添加${functionName}"; title.value = "添加${functionName}"
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
function handleUpdate(row) { function handleUpdate(row) {
reset(); reset()
const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
get${BusinessName}(_${pkColumn.javaField}).then(response => { get${BusinessName}(_${pkColumn.javaField}).then(response => {
form.value = response.data; form.value = response.data
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(","); form.value.$column.javaField = form.value.${column.javaField}.split(",")
#end #end
#end #end
#if($table.sub) #if($table.sub)
${subclassName}List.value = response.data.${subclassName}List; ${subclassName}List.value = response.data.${subclassName}List
#end #end
open.value = true; open.value = true
title.value = "修改${functionName}"; title.value = "修改${functionName}"
}); })
} }
/** 提交按钮 */ /** 提交按钮 */
@@ -508,68 +508,68 @@ function submitForm() {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(","); form.value.$column.javaField = form.value.${column.javaField}.join(",")
#end #end
#end #end
#if($table.sub) #if($table.sub)
form.value.${subclassName}List = ${subclassName}List.value; form.value.${subclassName}List = ${subclassName}List.value
#end #end
if (form.value.${pkColumn.javaField} != null) { if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => { update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功"); proxy.#[[$modal]]#.msgSuccess("修改成功")
open.value = false; open.value = false
getList(); getList()
}); })
} else { } else {
add${BusinessName}(form.value).then(response => { add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功"); proxy.#[[$modal]]#.msgSuccess("新增成功")
open.value = false; open.value = false
getList(); getList()
}); })
} }
} }
}); })
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
function handleDelete(row) { function handleDelete(row) {
const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value; const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() { proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(_${pkColumn.javaField}s); return del${BusinessName}(_${pkColumn.javaField}s)
}).then(() => { }).then(() => {
getList(); getList()
proxy.#[[$modal]]#.msgSuccess("删除成功"); proxy.#[[$modal]]#.msgSuccess("删除成功")
}).catch(() => {}); }).catch(() => {})
} }
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
function row${subClassName}Index({ row, rowIndex }) { function row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1; row.index = rowIndex + 1
} }
/** ${subTable.functionName}添加按钮操作 */ /** ${subTable.functionName}添加按钮操作 */
function handleAdd${subClassName}() { function handleAdd${subClassName}() {
let obj = {}; let obj = {}
#foreach($column in $subTable.columns) #foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName}) #if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
obj.$column.javaField = ""; obj.$column.javaField = ""
#end #end
#end #end
${subclassName}List.value.push(obj); ${subclassName}List.value.push(obj)
} }
/** ${subTable.functionName}删除按钮操作 */ /** ${subTable.functionName}删除按钮操作 */
function handleDelete${subClassName}() { function handleDelete${subClassName}() {
if (checked${subClassName}.value.length == 0) { if (checked${subClassName}.value.length == 0) {
proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据"); proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据")
} else { } else {
const ${subclassName}s = ${subclassName}List.value; const ${subclassName}s = ${subclassName}List.value
const checked${subClassName}s = checked${subClassName}.value; const checked${subClassName}s = checked${subClassName}.value
${subclassName}List.value = ${subclassName}s.filter(function(item) { ${subclassName}List.value = ${subclassName}s.filter(function(item) {
return checked${subClassName}s.indexOf(item.index) == -1 return checked${subClassName}s.indexOf(item.index) == -1
}); })
} }
} }
@@ -586,5 +586,5 @@ function handleExport() {
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
} }
getList(); getList()
</script> </script>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -178,7 +178,7 @@ public class SysJobController extends BaseController
@RequiresPermissions("monitor:job:remove") @RequiresPermissions("monitor:job:remove")
@Log(title = "定时任务", businessType = BusinessType.DELETE) @Log(title = "定时任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{jobIds}") @DeleteMapping("/{jobIds}")
public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException
{ {
jobService.deleteJobByIds(jobIds); jobService.deleteJobByIds(jobIds);
return success(); return success();

View File

@@ -3,7 +3,6 @@ package com.ruoyi.job.util;
import java.util.Date; import java.util.Date;
import org.quartz.Job; import org.quartz.Job;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.ruoyi.common.core.constant.ScheduleConstants; import com.ruoyi.common.core.constant.ScheduleConstants;
@@ -30,7 +29,7 @@ public abstract class AbstractQuartzJob implements Job
private static ThreadLocal<Date> threadLocal = new ThreadLocal<>(); private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
@Override @Override
public void execute(JobExecutionContext context) throws JobExecutionException public void execute(JobExecutionContext context)
{ {
SysJob sysJob = new SysJob(); SysJob sysJob = new SysJob();
BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));

View File

@@ -105,7 +105,7 @@ public class JobInvokeUtil
*/ */
public static List<Object[]> getMethodParams(String invokeTarget) public static List<Object[]> getMethodParams(String invokeTarget)
{ {
String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")"); String methodStr = StringUtils.substringBetweenLast(invokeTarget, "(", ")");
if (StringUtils.isEmpty(methodStr)) if (StringUtils.isEmpty(methodStr))
{ {
return null; return null;

View File

@@ -131,11 +131,11 @@ public class ScheduleUtils
int count = StringUtils.countMatches(packageName, "."); int count = StringUtils.countMatches(packageName, ".");
if (count > 1) if (count > 1)
{ {
return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR); return StringUtils.startsWithAny(invokeTarget, Constants.JOB_WHITELIST_STR);
} }
Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]); Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]);
String beanPackageName = obj.getClass().getPackage().getName(); String beanPackageName = obj.getClass().getPackage().getName();
return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR) return StringUtils.startsWithAny(beanPackageName, Constants.JOB_WHITELIST_STR)
&& !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR); && !StringUtils.startsWithAny(beanPackageName, Constants.JOB_ERROR_STR);
} }
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.5</version> <version>3.6.6</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1,6 +1,7 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@@ -11,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileTypeUtils; import com.ruoyi.common.core.utils.file.FileTypeUtils;
import com.ruoyi.common.core.utils.file.MimeTypeUtils; import com.ruoyi.common.core.utils.file.MimeTypeUtils;
@@ -93,10 +95,13 @@ public class SysProfileController extends BaseController
*/ */
@Log(title = "个人信息", businessType = BusinessType.UPDATE) @Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/updatePwd") @PutMapping("/updatePwd")
public AjaxResult updatePwd(String oldPassword, String newPassword) public AjaxResult updatePwd(@RequestBody Map<String, String> params)
{ {
String username = SecurityUtils.getUsername(); String oldPassword = params.get("oldPassword");
SysUser user = userService.selectUserByUserName(username); String newPassword = params.get("newPassword");
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userId = loginUser.getUserid();
SysUser user = userService.selectUserById(userId);
String password = user.getPassword(); String password = user.getPassword();
if (!SecurityUtils.matchesPassword(oldPassword, password)) if (!SecurityUtils.matchesPassword(oldPassword, password))
{ {
@@ -107,10 +112,10 @@ public class SysProfileController extends BaseController
return error("新密码不能与旧密码相同"); return error("新密码不能与旧密码相同");
} }
newPassword = SecurityUtils.encryptPassword(newPassword); newPassword = SecurityUtils.encryptPassword(newPassword);
if (userService.resetUserPwd(username, newPassword) > 0) if (userService.resetUserPwd(userId, newPassword) > 0)
{ {
// 更新缓存用户密码 // 更新缓存用户密码&密码最后更新时间
LoginUser loginUser = SecurityUtils.getLoginUser(); loginUser.getSysUser().setPwdUpdateDate(DateUtils.getNowDate());
loginUser.getSysUser().setPassword(newPassword); loginUser.getSysUser().setPassword(newPassword);
tokenService.setLoginUser(loginUser); tokenService.setLoginUser(loginUser);
return success(); return success();
@@ -139,8 +144,13 @@ public class SysProfileController extends BaseController
return error("文件服务异常,请联系管理员"); return error("文件服务异常,请联系管理员");
} }
String url = fileResult.getData().getUrl(); String url = fileResult.getData().getUrl();
if (userService.updateUserAvatar(loginUser.getUsername(), url)) if (userService.updateUserAvatar(loginUser.getUserid(), url))
{ {
String oldAvatarUrl = loginUser.getSysUser().getAvatar();
if (StringUtils.isNotEmpty(oldAvatarUrl))
{
remoteFileService.delete(oldAvatarUrl);
}
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", url); ajax.put("imgUrl", url);
// 更新缓存用户头像 // 更新缓存用户头像

View File

@@ -1,6 +1,7 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.io.IOException; import java.io.IOException;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -18,6 +19,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.controller.BaseController;
@@ -160,7 +163,7 @@ public class SysUserController extends BaseController
@PutMapping("/recordlogin") @PutMapping("/recordlogin")
public R<Boolean> recordlogin(@RequestBody SysUser sysUser) public R<Boolean> recordlogin(@RequestBody SysUser sysUser)
{ {
return R.ok(userService.updateUserProfile(sysUser)); return R.ok(userService.updateLoginInfo(sysUser));
} }
/** /**
@@ -186,9 +189,35 @@ public class SysUserController extends BaseController
ajax.put("user", user); ajax.put("user", user);
ajax.put("roles", roles); ajax.put("roles", roles);
ajax.put("permissions", permissions); ajax.put("permissions", permissions);
ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
return ajax; return ajax;
} }
// 检查初始密码是否提醒修改
public boolean initPasswordIsModify(Date pwdUpdateDate)
{
Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
}
// 检查密码是否过期
public boolean passwordIsExpiration(Date pwdUpdateDate)
{
Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
if (passwordValidateDays != null && passwordValidateDays > 0)
{
if (StringUtils.isNull(pwdUpdateDate))
{
// 如果从未修改过初始密码,直接提醒过期
return true;
}
Date nowDate = DateUtils.getNowDate();
return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
}
return false;
}
/** /**
* 根据用户编号获取详细信息 * 根据用户编号获取详细信息
*/ */

View File

@@ -4,6 +4,8 @@ import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.api.domain.SysDept;
import com.ruoyi.system.domain.SysMenu; import com.ruoyi.system.domain.SysMenu;
@@ -22,6 +24,9 @@ public class TreeSelect implements Serializable
/** 节点名称 */ /** 节点名称 */
private String label; private String label;
/** 节点禁用 */
private boolean disabled = false;
/** 子节点 */ /** 子节点 */
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<TreeSelect> children; private List<TreeSelect> children;
@@ -35,6 +40,7 @@ public class TreeSelect implements Serializable
{ {
this.id = dept.getDeptId(); this.id = dept.getDeptId();
this.label = dept.getDeptName(); this.label = dept.getDeptName();
this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
} }
@@ -65,6 +71,16 @@ public class TreeSelect implements Serializable
this.label = label; this.label = label;
} }
public boolean isDisabled()
{
return disabled;
}
public void setDisabled(boolean disabled)
{
this.disabled = disabled;
}
public List<TreeSelect> getChildren() public List<TreeSelect> getChildren()
{ {
return children; return children;

View File

@@ -70,20 +70,37 @@ public interface SysUserMapper
/** /**
* 修改用户头像 * 修改用户头像
* *
* @param userName 用户 * @param userId 用户ID
* @param avatar 头像地址 * @param avatar 头像地址
* @return 结果 * @return 结果
*/ */
public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar); public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar);
/**
* 修改用户状态
*
* @param userId 用户ID
* @param status 状态
* @return 结果
*/
public int updateUserStatus(@Param("userId") Long userId, @Param("status") String status);
/**
* 更新用户登录信息IP和登录时间
*
* @param user 用户信息
* @return 结果
*/
public int updateLoginInfo(SysUser user);
/** /**
* 重置用户密码 * 重置用户密码
* *
* @param userName 用户 * @param userId 用户ID
* @param password 密码 * @param password 密码
* @return 结果 * @return 结果
*/ */
public int resetUserPwd(@Param("userName") String userName, @Param("password") String password); public int resetUserPwd(@Param("userId") Long userId, @Param("password") String password);
/** /**
* 通过用户ID删除用户 * 通过用户ID删除用户

View File

@@ -155,11 +155,19 @@ public interface ISysUserService
/** /**
* 修改用户头像 * 修改用户头像
* *
* @param userName 用户 * @param userId 用户ID
* @param avatar 头像地址 * @param avatar 头像地址
* @return 结果 * @return 结果
*/ */
public boolean updateUserAvatar(String userName, String avatar); public boolean updateUserAvatar(Long userId, String avatar);
/**
* 更新用户登录信息IP和登录时间
*
* @param user 用户信息
* @return 结果
*/
public boolean updateLoginInfo(SysUser user);
/** /**
* 重置用户密码 * 重置用户密码
@@ -172,11 +180,11 @@ public interface ISysUserService
/** /**
* 重置用户密码 * 重置用户密码
* *
* @param userName 用户 * @param userId 用户ID
* @param password 密码 * @param password 密码
* @return 结果 * @return 结果
*/ */
public int resetUserPwd(String userName, String password); public int resetUserPwd(Long userId, String password);
/** /**
* 通过用户ID删除用户 * 通过用户ID删除用户

View File

@@ -365,7 +365,7 @@ public class SysMenuServiceImpl implements ISysMenuService
/** /**
* 获取路由名称,如没有配置路由名称则取路由地址 * 获取路由名称,如没有配置路由名称则取路由地址
* *
* @param routerName 路由名称 * @param name 路由名称
* @param path 路由地址 * @param path 路由地址
* @return 路由名称(驼峰格式) * @return 路由名称(驼峰格式)
*/ */

View File

@@ -6,6 +6,7 @@ import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysRole;
@@ -41,7 +42,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService
// 管理员拥有所有权限 // 管理员拥有所有权限
if (user.isAdmin()) if (user.isAdmin())
{ {
roles.add("admin"); roles.add(Constants.SUPER_ADMIN);
} }
else else
{ {
@@ -63,7 +64,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService
// 管理员拥有所有权限 // 管理员拥有所有权限
if (user.isAdmin()) if (user.isAdmin())
{ {
perms.add("*:*:*"); perms.add(Constants.ALL_PERMISSION);
} }
else else
{ {
@@ -73,7 +74,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService
// 多角色设置permissions属性以便数据权限匹配权限 // 多角色设置permissions属性以便数据权限匹配权限
for (SysRole role : roles) for (SysRole role : roles)
{ {
if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL)) if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && !role.isAdmin())
{ {
Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId()); Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
role.setPermissions(rolePerms); role.setPermissions(rolePerms);

View File

@@ -326,7 +326,7 @@ public class SysUserServiceImpl implements ISysUserService
@Override @Override
public int updateUserStatus(SysUser user) public int updateUserStatus(SysUser user)
{ {
return userMapper.updateUser(user); return userMapper.updateUserStatus(user.getUserId(), user.getStatus());
} }
/** /**
@@ -344,14 +344,25 @@ public class SysUserServiceImpl implements ISysUserService
/** /**
* 修改用户头像 * 修改用户头像
* *
* @param userName 用户 * @param userId 用户ID
* @param avatar 头像地址 * @param avatar 头像地址
* @return 结果 * @return 结果
*/ */
@Override @Override
public boolean updateUserAvatar(String userName, String avatar) public boolean updateUserAvatar(Long userId, String avatar)
{ {
return userMapper.updateUserAvatar(userName, avatar) > 0; return userMapper.updateUserAvatar(userId, avatar) > 0;
}
/**
* 更新用户登录信息IP和登录时间
*
* @param user 用户信息
* @return 结果
*/
public boolean updateLoginInfo(SysUser user)
{
return userMapper.updateLoginInfo(user) > 0;
} }
/** /**
@@ -363,20 +374,20 @@ public class SysUserServiceImpl implements ISysUserService
@Override @Override
public int resetPwd(SysUser user) public int resetPwd(SysUser user)
{ {
return userMapper.updateUser(user); return userMapper.resetUserPwd(user.getUserId(), user.getPassword());
} }
/** /**
* 重置用户密码 * 重置用户密码
* *
* @param userName 用户 * @param userId 用户ID
* @param password 密码 * @param password 密码
* @return 结果 * @return 结果
*/ */
@Override @Override
public int resetUserPwd(String userName, String password) public int resetUserPwd(Long userId, String password)
{ {
return userMapper.resetUserPwd(userName, password); return userMapper.resetUserPwd(userId, password);
} }
/** /**
@@ -517,6 +528,7 @@ public class SysUserServiceImpl implements ISysUserService
checkUserDataScope(u.getUserId()); checkUserDataScope(u.getUserId());
deptService.checkDeptDataScope(user.getDeptId()); deptService.checkDeptDataScope(user.getDeptId());
user.setUserId(u.getUserId()); user.setUserId(u.getUserId());
user.setDeptId(u.getDeptId());
user.setUpdateBy(operName); user.setUpdateBy(operName);
userMapper.updateUser(user); userMapper.updateUser(user);
successNum++; successNum++;

View File

@@ -149,7 +149,7 @@
<if test="visible != null">visible = #{visible},</if> <if test="visible != null">visible = #{visible},</if>
<if test="status != null">status = #{status},</if> <if test="status != null">status = #{status},</if>
<if test="perms !=null">perms = #{perms},</if> <if test="perms !=null">perms = #{perms},</if>
<if test="icon !=null and icon != ''">icon = #{icon},</if> icon = #{icon},
<if test="remark != null and remark != ''">remark = #{remark},</if> <if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
update_time = sysdate() update_time = sysdate()

View File

@@ -5,26 +5,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<mapper namespace="com.ruoyi.system.mapper.SysUserMapper"> <mapper namespace="com.ruoyi.system.mapper.SysUserMapper">
<resultMap type="SysUser" id="SysUserResult"> <resultMap type="SysUser" id="SysUserResult">
<id property="userId" column="user_id" /> <id property="userId" column="user_id" />
<result property="deptId" column="dept_id" /> <result property="deptId" column="dept_id" />
<result property="userName" column="user_name" /> <result property="userName" column="user_name" />
<result property="nickName" column="nick_name" /> <result property="nickName" column="nick_name" />
<result property="email" column="email" /> <result property="email" column="email" />
<result property="phonenumber" column="phonenumber" /> <result property="phonenumber" column="phonenumber" />
<result property="sex" column="sex" /> <result property="sex" column="sex" />
<result property="avatar" column="avatar" /> <result property="avatar" column="avatar" />
<result property="password" column="password" /> <result property="password" column="password" />
<result property="status" column="status" /> <result property="status" column="status" />
<result property="delFlag" column="del_flag" /> <result property="delFlag" column="del_flag" />
<result property="loginIp" column="login_ip" /> <result property="loginIp" column="login_ip" />
<result property="loginDate" column="login_date" /> <result property="loginDate" column="login_date" />
<result property="createBy" column="create_by" /> <result property="pwdUpdateDate" column="pwd_update_date" />
<result property="createTime" column="create_time" /> <result property="createBy" column="create_by" />
<result property="updateBy" column="update_by" /> <result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" /> <result property="updateBy" column="update_by" />
<result property="remark" column="remark" /> <result property="updateTime" column="update_time" />
<association property="dept" javaType="SysDept" resultMap="deptResult" /> <result property="remark" column="remark" />
<collection property="roles" javaType="java.util.List" resultMap="RoleResult" /> <association property="dept" javaType="SysDept" resultMap="deptResult" />
<collection property="roles" javaType="java.util.List" resultMap="RoleResult" />
</resultMap> </resultMap>
<resultMap id="deptResult" type="SysDept"> <resultMap id="deptResult" type="SysDept">
@@ -47,7 +48,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectUserVo"> <sql id="selectUserVo">
select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.pwd_update_date, u.create_by, u.create_time, u.remark,
d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
from sys_user u from sys_user u
@@ -154,6 +155,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sex != null and sex != ''">sex,</if> <if test="sex != null and sex != ''">sex,</if>
<if test="password != null and password != ''">password,</if> <if test="password != null and password != ''">password,</if>
<if test="status != null and status != ''">status,</if> <if test="status != null and status != ''">status,</if>
<if test="pwdUpdateDate != null">pwd_update_date,</if>
<if test="createBy != null and createBy != ''">create_by,</if> <if test="createBy != null and createBy != ''">create_by,</if>
<if test="remark != null and remark != ''">remark,</if> <if test="remark != null and remark != ''">remark,</if>
create_time create_time
@@ -168,6 +170,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sex != null and sex != ''">#{sex},</if> <if test="sex != null and sex != ''">#{sex},</if>
<if test="password != null and password != ''">#{password},</if> <if test="password != null and password != ''">#{password},</if>
<if test="status != null and status != ''">#{status},</if> <if test="status != null and status != ''">#{status},</if>
<if test="pwdUpdateDate != null">#{pwdUpdateDate},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if> <if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="remark != null and remark != ''">#{remark},</if> <if test="remark != null and remark != ''">#{remark},</if>
sysdate() sysdate()
@@ -177,8 +180,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<update id="updateUser" parameterType="SysUser"> <update id="updateUser" parameterType="SysUser">
update sys_user update sys_user
<set> <set>
<if test="deptId != null and deptId != 0">dept_id = #{deptId},</if> <if test="deptId != 0">dept_id = #{deptId},</if>
<if test="userName != null and userName != ''">user_name = #{userName},</if>
<if test="nickName != null and nickName != ''">nick_name = #{nickName},</if> <if test="nickName != null and nickName != ''">nick_name = #{nickName},</if>
<if test="email != null ">email = #{email},</if> <if test="email != null ">email = #{email},</if>
<if test="phonenumber != null ">phonenumber = #{phonenumber},</if> <if test="phonenumber != null ">phonenumber = #{phonenumber},</if>
@@ -196,15 +198,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</update> </update>
<update id="updateUserStatus" parameterType="SysUser"> <update id="updateUserStatus" parameterType="SysUser">
update sys_user set status = #{status} where user_id = #{userId} update sys_user set status = #{status}, update_time = sysdate() where user_id = #{userId}
</update> </update>
<update id="updateUserAvatar" parameterType="SysUser"> <update id="updateUserAvatar" parameterType="SysUser">
update sys_user set avatar = #{avatar} where user_name = #{userName} update sys_user set avatar = #{avatar}, update_time = sysdate() where user_id = #{userId}
</update>
<update id="updateLoginInfo" parameterType="SysUser">
update sys_user set login_ip = #{loginIp}, login_date = #{loginDate} where user_id = #{userId}
</update> </update>
<update id="resetUserPwd" parameterType="SysUser"> <update id="resetUserPwd" parameterType="SysUser">
update sys_user set password = #{password} where user_name = #{userName} update sys_user set pwd_update_date = sysdate(), password = #{password}, update_time = sysdate() where user_id = #{userId}
</update> </update>
<delete id="deleteUserById" parameterType="Long"> <delete id="deleteUserById" parameterType="Long">

View File

@@ -1,6 +1,8 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 若依管理系统
BABEL_ENV = production
NODE_ENV = production NODE_ENV = production
# 测试环境配置 # 测试环境配置

View File

@@ -1,10 +0,0 @@
# 忽略build目录下类型为js的文件的语法检查
build/*.js
# 忽略src/assets目录下文件的语法检查
src/assets
# 忽略public目录下文件的语法检查
public
# 忽略当前目录下为js的文件的语法检查
*.js
# 忽略当前目录下为vue的文件的语法检查
*.vue

View File

@@ -1,199 +0,0 @@
// ESlint 检查配置
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'never'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
}

View File

@@ -1,6 +1,6 @@
{ {
"name": "ruoyi", "name": "ruoyi",
"version": "3.6.5", "version": "3.6.6",
"description": "若依管理系统", "description": "若依管理系统",
"author": "若依", "author": "若依",
"license": "MIT", "license": "MIT",
@@ -8,19 +8,7 @@
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build", "build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging", "build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview", "preview": "node build/index.js --preview"
"lint": "eslint --ext .js,.vue src"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
}, },
"keywords": [ "keywords": [
"vue", "vue",
@@ -52,27 +40,21 @@
"quill": "2.0.2", "quill": "2.0.2",
"screenfull": "5.0.2", "screenfull": "5.0.2",
"sortablejs": "1.10.2", "sortablejs": "1.10.2",
"splitpanes": "2.4.1",
"vue": "2.6.12", "vue": "2.6.12",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",
"vue-meta": "2.4.0",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vuedraggable": "2.24.3", "vuedraggable": "2.24.3",
"vuex": "3.6.0" "vuex": "3.6.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "4.4.6", "@vue/cli-plugin-babel": "4.4.6",
"@vue/cli-plugin-eslint": "4.4.6",
"@vue/cli-service": "4.4.6", "@vue/cli-service": "4.4.6",
"babel-eslint": "10.1.0",
"babel-plugin-dynamic-import-node": "2.3.3", "babel-plugin-dynamic-import-node": "2.3.3",
"chalk": "4.1.0", "chalk": "4.1.0",
"compression-webpack-plugin": "6.1.2", "compression-webpack-plugin": "6.1.2",
"connect": "3.6.6", "connect": "3.6.6",
"eslint": "7.15.0",
"eslint-plugin-vue": "7.2.0",
"lint-staged": "10.5.3",
"runjs": "4.4.2",
"sass": "1.32.13", "sass": "1.32.13",
"sass-loader": "10.1.1", "sass-loader": "10.1.1",
"script-ext-html-webpack-plugin": "2.1.5", "script-ext-html-webpack-plugin": "2.1.5",

File diff suppressed because one or more lines are too long

View File

@@ -6,20 +6,12 @@
</template> </template>
<script> <script>
import ThemePicker from "@/components/ThemePicker"; import ThemePicker from "@/components/ThemePicker"
export default { export default {
name: "App", name: "App",
components: { ThemePicker }, components: { ThemePicker }
metaInfo() { }
return {
title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
titleTemplate: title => {
return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
}
}
}
};
</script> </script>
<style scoped> <style scoped>
#app .theme-picker { #app .theme-picker {

View File

@@ -96,7 +96,7 @@ export function updateUserPwd(oldPassword, newPassword) {
return request({ return request({
url: '/system/user/profile/updatePwd', url: '/system/user/profile/updatePwd',
method: 'put', method: 'put',
params: data data: data
}) })
} }

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746590936918" class="icon" viewBox="0 0 1194 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5378" xmlns:xlink="http://www.w3.org/1999/xlink" width="233.203125" height="200"><path d="M1151.9144 325.11999969V89.12a57.04000031 57.04000031 0 0 0-28.8-49.44 58.15999969 58.15999969 0 0 0-57.76000031 0 57.04000031 57.04000031 0 0 0-28.8 49.44v235.99999969c0.24 84.31999969-33.6 152.56000031-94.08 212.00000062-60.07999969 59.83999969-141.84 80.64-227.04 80.4H225.91440031L388.07439969 457.11999969a56.80000031 56.80000031 0 0 0 12.40000031-62.16 57.76000031 57.76000031 0 0 0-94.00000031-18.63999938L48.8744 631.20000031a56.88 56.88 0 0 0 0 80.79999938l264.96 262.56a58.08 58.08 0 0 0 96.55999969-25.59999938 56.80000031 56.80000031 0 0 0-14.95999969-55.2L232.07439969 731.67999969h483.44000062c116.56000031 0 226.15999969-32.08000031 308.64-113.76 82.15999969-80.80000031 128.23999969-178.15999969 127.83999938-292.87999969" p-id="5379"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746760911144" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12537" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M395.21211 182.914448c0 62.669318 49.541323 113.472378 110.642936 113.472378 61.093427 0 110.652146-50.80306 110.65214601-113.472378 0-62.685691-49.559742-113.487727-110.65214601-113.487727C444.75241 69.426721 395.21211 120.22978 395.21211 182.914448zM395.21211 523.34693101c0 62.668295 49.541323 113.487727 110.642936 113.48772699 61.093427 0 110.652146-50.820456 110.652146-113.487727 0-62.669318-49.559742-113.472378-110.652146-113.472378C444.75241 409.874553 395.21211 460.67761301 395.21211 523.34693101zM395.21211 841.084529c0 62.686714 49.541323 113.488751 110.642936 113.488751 61.093427 0 110.652146-50.80203599 110.65214601-113.488751 0-62.669318-49.559742-113.471354-110.65214601-113.471354C444.75241 727.614198 395.21211 778.416234 395.21211 841.084529z" p-id="12538"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -129,10 +129,6 @@ aside {
position: relative; position: relative;
} }
.pagination-container {
margin-top: 30px;
}
.text-center { .text-center {
text-align: center text-align: center
} }

View File

@@ -117,11 +117,9 @@
/** 表格布局 **/ /** 表格布局 **/
.pagination-container { .pagination-container {
position: relative; display: flex;
height: 25px; justify-content: flex-end;
margin-bottom: 10px; margin-top: 20px;
margin-top: 15px;
padding: 10px 20px !important;
} }
/* tree border */ /* tree border */
@@ -132,11 +130,6 @@
border-radius: 4px; border-radius: 4px;
} }
.pagination-container .el-pagination {
right: 0;
position: absolute;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.pagination-container .el-pagination > .el-pagination__jump { .pagination-container .el-pagination > .el-pagination__jump {
display: none !important; display: none !important;
@@ -201,8 +194,6 @@
} }
.card-box { .card-box {
padding-right: 15px;
padding-left: 15px;
margin-bottom: 10px; margin-bottom: 10px;
} }
@@ -289,3 +280,8 @@
position: relative; position: relative;
float: right; float: right;
} }
/* 分割面板样式 */
.splitpanes.default-theme .splitpanes__pane {
background-color: #fff!important;
}

View File

@@ -25,7 +25,7 @@
z-index: 1001; z-index: 1001;
overflow: hidden; overflow: hidden;
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35); -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
box-shadow: 2px 0 6px rgba(0,21,41,.35); box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
// reset element-ui css // reset element-ui css
.horizontal-collapse-transition { .horizontal-collapse-transition {

View File

@@ -1,7 +1,7 @@
<template> <template>
<el-breadcrumb class="app-breadcrumb" separator="/"> <el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb"> <transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path"> <el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span> <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a> <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item> </el-breadcrumb-item>
@@ -31,15 +31,45 @@ export default {
methods: { methods: {
getBreadcrumb() { getBreadcrumb() {
// only show routes with meta.title // only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title) let matched = []
const first = matched[0] const router = this.$route
const pathNum = this.findPathNum(router.path)
if (!this.isDashboard(first)) { // multi-level menu
matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched) if (pathNum > 2) {
const reg = /\/\w+/gi
const pathList = router.path.match(reg).map((item, index) => {
if (index !== 0) item = item.slice(1)
return item
})
this.getMatched(pathList, this.$store.getters.defaultRoutes, matched)
} else {
matched = router.matched.filter(item => item.meta && item.meta.title)
}
// 判断是否为首页
if (!this.isDashboard(matched[0])) {
matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched)
} }
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
}, },
findPathNum(str, char = "/") {
let index = str.indexOf(char)
let num = 0
while (index !== -1) {
num++
index = str.indexOf(char, index + 1)
}
return num
},
getMatched(pathList, routeList, matched) {
let data = routeList.find(item => item.path == pathList[0] || (item.name += '').toLowerCase() == pathList[0])
if (data) {
matched.push(data)
if (data.children && pathList.length) {
pathList.shift()
this.getMatched(pathList, data.children, matched)
}
}
},
isDashboard(route) { isDashboard(route) {
const name = route && route.name const name = route && route.name
if (!name) { if (!name) {
@@ -65,7 +95,6 @@ export default {
font-size: 14px; font-size: 14px;
line-height: 50px; line-height: 50px;
margin-left: 8px; margin-left: 8px;
.no-redirect { .no-redirect {
color: #97a8be; color: #97a8be;
cursor: text; cursor: text;

View File

@@ -71,58 +71,58 @@ export default {
methods: { methods: {
// 单选按钮值变化时 // 单选按钮值变化时
radioChange() { radioChange() {
('day rachange'); ('day rachange')
if (this.radioValue !== 2 && this.cron.week !== '?') { if (this.radioValue !== 2 && this.cron.week !== '?') {
this.$emit('update', 'week', '?', 'day') this.$emit('update', 'week', '?', 'day')
} }
switch (this.radioValue) { switch (this.radioValue) {
case 1: case 1:
this.$emit('update', 'day', '*'); this.$emit('update', 'day', '*')
break; break
case 2: case 2:
this.$emit('update', 'day', '?'); this.$emit('update', 'day', '?')
break; break
case 3: case 3:
this.$emit('update', 'day', this.cycleTotal); this.$emit('update', 'day', this.cycleTotal)
break; break
case 4: case 4:
this.$emit('update', 'day', this.averageTotal); this.$emit('update', 'day', this.averageTotal)
break; break
case 5: case 5:
this.$emit('update', 'day', this.workday + 'W'); this.$emit('update', 'day', this.workday + 'W')
break; break
case 6: case 6:
this.$emit('update', 'day', 'L'); this.$emit('update', 'day', 'L')
break; break
case 7: case 7:
this.$emit('update', 'day', this.checkboxString); this.$emit('update', 'day', this.checkboxString)
break; break
} }
('day rachange end'); ('day rachange end')
}, },
// 周期两个值变化时 // 周期两个值变化时
cycleChange() { cycleChange() {
if (this.radioValue == '3') { if (this.radioValue == '3') {
this.$emit('update', 'day', this.cycleTotal); this.$emit('update', 'day', this.cycleTotal)
} }
}, },
// 平均两个值变化时 // 平均两个值变化时
averageChange() { averageChange() {
if (this.radioValue == '4') { if (this.radioValue == '4') {
this.$emit('update', 'day', this.averageTotal); this.$emit('update', 'day', this.averageTotal)
} }
}, },
// 最近工作日值变化时 // 最近工作日值变化时
workdayChange() { workdayChange() {
if (this.radioValue == '5') { if (this.radioValue == '5') {
this.$emit('update', 'day', this.workdayCheck + 'W'); this.$emit('update', 'day', this.workdayCheck + 'W')
} }
}, },
// checkbox值变化时 // checkbox值变化时
checkboxChange() { checkboxChange() {
if (this.radioValue == '7') { if (this.radioValue == '7') {
this.$emit('update', 'day', this.checkboxString); this.$emit('update', 'day', this.checkboxString)
} }
} }
}, },
@@ -138,23 +138,23 @@ export default {
cycleTotal: function () { cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 1, 30) const cycle01 = this.checkNum(this.cycle01, 1, 30)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31) const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31)
return cycle01 + '-' + cycle02; return cycle01 + '-' + cycle02
}, },
// 计算平均用到的值 // 计算平均用到的值
averageTotal: function () { averageTotal: function () {
const average01 = this.checkNum(this.average01, 1, 30) const average01 = this.checkNum(this.average01, 1, 30)
const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0) const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0)
return average01 + '/' + average02; return average01 + '/' + average02
}, },
// 计算工作日格式 // 计算工作日格式
workdayCheck: function () { workdayCheck: function () {
const workday = this.checkNum(this.workday, 1, 31) const workday = this.checkNum(this.workday, 1, 31)
return workday; return workday
}, },
// 计算勾选的checkbox值合集 // 计算勾选的checkbox值合集
checkboxString: function () { checkboxString: function () {
let str = this.checkboxList.join(); let str = this.checkboxList.join()
return str == '' ? '*' : str; return str == '' ? '*' : str
} }
} }
} }

View File

@@ -51,37 +51,43 @@ export default {
methods: { methods: {
// 单选按钮值变化时 // 单选按钮值变化时
radioChange() { radioChange() {
if (this.cron.min === '*') {
this.$emit('update', 'min', '0', 'hour')
}
if (this.cron.second === '*') {
this.$emit('update', 'second', '0', 'hour')
}
switch (this.radioValue) { switch (this.radioValue) {
case 1: case 1:
this.$emit('update', 'hour', '*') this.$emit('update', 'hour', '*')
break; break
case 2: case 2:
this.$emit('update', 'hour', this.cycleTotal); this.$emit('update', 'hour', this.cycleTotal)
break; break
case 3: case 3:
this.$emit('update', 'hour', this.averageTotal); this.$emit('update', 'hour', this.averageTotal)
break; break
case 4: case 4:
this.$emit('update', 'hour', this.checkboxString); this.$emit('update', 'hour', this.checkboxString)
break; break
} }
}, },
// 周期两个值变化时 // 周期两个值变化时
cycleChange() { cycleChange() {
if (this.radioValue == '2') { if (this.radioValue == '2') {
this.$emit('update', 'hour', this.cycleTotal); this.$emit('update', 'hour', this.cycleTotal)
} }
}, },
// 平均两个值变化时 // 平均两个值变化时
averageChange() { averageChange() {
if (this.radioValue == '3') { if (this.radioValue == '3') {
this.$emit('update', 'hour', this.averageTotal); this.$emit('update', 'hour', this.averageTotal)
} }
}, },
// checkbox值变化时 // checkbox值变化时
checkboxChange() { checkboxChange() {
if (this.radioValue == '4') { if (this.radioValue == '4') {
this.$emit('update', 'hour', this.checkboxString); this.$emit('update', 'hour', this.checkboxString)
} }
} }
}, },
@@ -96,18 +102,18 @@ export default {
cycleTotal: function () { cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 0, 22) const cycle01 = this.checkNum(this.cycle01, 0, 22)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23) const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23)
return cycle01 + '-' + cycle02; return cycle01 + '-' + cycle02
}, },
// 计算平均用到的值 // 计算平均用到的值
averageTotal: function () { averageTotal: function () {
const average01 = this.checkNum(this.average01, 0, 22) const average01 = this.checkNum(this.average01, 0, 22)
const average02 = this.checkNum(this.average02, 1, 23 - average01 || 0) const average02 = this.checkNum(this.average02, 1, 23 - 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
} }
} }
} }

View File

@@ -113,14 +113,14 @@
</template> </template>
<script> <script>
import CrontabSecond from "./second.vue"; import CrontabSecond from "./second.vue"
import CrontabMin from "./min.vue"; import CrontabMin from "./min.vue"
import CrontabHour from "./hour.vue"; import CrontabHour from "./hour.vue"
import CrontabDay from "./day.vue"; import CrontabDay from "./day.vue"
import CrontabMonth from "./month.vue"; import CrontabMonth from "./month.vue"
import CrontabWeek from "./week.vue"; import CrontabWeek from "./week.vue"
import CrontabYear from "./year.vue"; import CrontabYear from "./year.vue"
import CrontabResult from "./result.vue"; import CrontabResult from "./result.vue"
export default { export default {
data() { data() {
@@ -137,19 +137,19 @@ export default {
week: "?", week: "?",
year: "", year: "",
}, },
}; }
}, },
name: "vcrontab", name: "vcrontab",
props: ["expression", "hideComponent"], props: ["expression", "hideComponent"],
methods: { methods: {
shouldHide(key) { shouldHide(key) {
if (this.hideComponent && this.hideComponent.includes(key)) return false; if (this.hideComponent && this.hideComponent.includes(key)) return false
return true; return true
}, },
resolveExp() { resolveExp() {
// 反解析 表达式 // 反解析 表达式
if (this.expression) { if (this.expression) {
let arr = this.expression.split(" "); let arr = this.expression.split(" ")
if (arr.length >= 6) { if (arr.length >= 6) {
//6 位以上是合法表达式 //6 位以上是合法表达式
let obj = { let obj = {
@@ -160,160 +160,160 @@ export default {
month: arr[4], month: arr[4],
week: arr[5], week: arr[5],
year: arr[6] ? arr[6] : "", year: arr[6] ? arr[6] : "",
}; }
this.crontabValueObj = { this.crontabValueObj = {
...obj, ...obj,
}; }
for (let i in obj) { for (let i in obj) {
if (obj[i]) this.changeRadio(i, obj[i]); if (obj[i]) this.changeRadio(i, obj[i])
} }
} }
} else { } else {
// 没有传入的表达式 则还原 // 没有传入的表达式 则还原
this.clearCron(); this.clearCron()
} }
}, },
// tab切换值 // tab切换值
tabCheck(index) { tabCheck(index) {
this.tabActive = index; this.tabActive = index
}, },
// 由子组件触发,更改表达式组成的字段值 // 由子组件触发,更改表达式组成的字段值
updateCrontabValue(name, value, from) { updateCrontabValue(name, value, from) {
"updateCrontabValue", name, value, from; "updateCrontabValue", name, value, from
this.crontabValueObj[name] = value; this.crontabValueObj[name] = value
if (from && from !== name) { if (from && from !== name) {
console.log(`来自组件 ${from} 改变了 ${name} ${value}`); console.log(`来自组件 ${from} 改变了 ${name} ${value}`)
this.changeRadio(name, value); this.changeRadio(name, value)
} }
}, },
// 赋值到组件 // 赋值到组件
changeRadio(name, value) { changeRadio(name, value) {
let arr = ["second", "min", "hour", "month"], let arr = ["second", "min", "hour", "month"],
refName = "cron" + name, refName = "cron" + name,
insValue; insValue
if (!this.$refs[refName]) return; if (!this.$refs[refName]) return
if (arr.includes(name)) { if (arr.includes(name)) {
if (value === "*") { if (value === "*") {
insValue = 1; insValue = 1
} else if (value.indexOf("-") > -1) { } else if (value.indexOf("-") > -1) {
let indexArr = value.split("-"); let indexArr = value.split("-")
isNaN(indexArr[0]) isNaN(indexArr[0])
? (this.$refs[refName].cycle01 = 0) ? (this.$refs[refName].cycle01 = 0)
: (this.$refs[refName].cycle01 = indexArr[0]); : (this.$refs[refName].cycle01 = indexArr[0])
this.$refs[refName].cycle02 = indexArr[1]; this.$refs[refName].cycle02 = indexArr[1]
insValue = 2; insValue = 2
} else if (value.indexOf("/") > -1) { } else if (value.indexOf("/") > -1) {
let indexArr = value.split("/"); let indexArr = value.split("/")
isNaN(indexArr[0]) isNaN(indexArr[0])
? (this.$refs[refName].average01 = 0) ? (this.$refs[refName].average01 = 0)
: (this.$refs[refName].average01 = indexArr[0]); : (this.$refs[refName].average01 = indexArr[0])
this.$refs[refName].average02 = indexArr[1]; this.$refs[refName].average02 = indexArr[1]
insValue = 3; insValue = 3
} else { } else {
insValue = 4; insValue = 4
this.$refs[refName].checkboxList = value.split(","); this.$refs[refName].checkboxList = value.split(",")
} }
} else if (name == "day") { } else if (name == "day") {
if (value === "*") { if (value === "*") {
insValue = 1; insValue = 1
} else if (value == "?") { } else if (value == "?") {
insValue = 2; insValue = 2
} else if (value.indexOf("-") > -1) { } else if (value.indexOf("-") > -1) {
let indexArr = value.split("-"); let indexArr = value.split("-")
isNaN(indexArr[0]) isNaN(indexArr[0])
? (this.$refs[refName].cycle01 = 0) ? (this.$refs[refName].cycle01 = 0)
: (this.$refs[refName].cycle01 = indexArr[0]); : (this.$refs[refName].cycle01 = indexArr[0])
this.$refs[refName].cycle02 = indexArr[1]; this.$refs[refName].cycle02 = indexArr[1]
insValue = 3; insValue = 3
} else if (value.indexOf("/") > -1) { } else if (value.indexOf("/") > -1) {
let indexArr = value.split("/"); let indexArr = value.split("/")
isNaN(indexArr[0]) isNaN(indexArr[0])
? (this.$refs[refName].average01 = 0) ? (this.$refs[refName].average01 = 0)
: (this.$refs[refName].average01 = indexArr[0]); : (this.$refs[refName].average01 = indexArr[0])
this.$refs[refName].average02 = indexArr[1]; this.$refs[refName].average02 = indexArr[1]
insValue = 4; insValue = 4
} else if (value.indexOf("W") > -1) { } else if (value.indexOf("W") > -1) {
let indexArr = value.split("W"); let indexArr = value.split("W")
isNaN(indexArr[0]) isNaN(indexArr[0])
? (this.$refs[refName].workday = 0) ? (this.$refs[refName].workday = 0)
: (this.$refs[refName].workday = indexArr[0]); : (this.$refs[refName].workday = indexArr[0])
insValue = 5; insValue = 5
} else if (value === "L") { } else if (value === "L") {
insValue = 6; insValue = 6
} else { } else {
this.$refs[refName].checkboxList = value.split(","); this.$refs[refName].checkboxList = value.split(",")
insValue = 7; insValue = 7
} }
} else if (name == "week") { } else if (name == "week") {
if (value === "*") { if (value === "*") {
insValue = 1; insValue = 1
} else if (value == "?") { } else if (value == "?") {
insValue = 2; insValue = 2
} else if (value.indexOf("-") > -1) { } else if (value.indexOf("-") > -1) {
let indexArr = value.split("-"); let indexArr = value.split("-")
isNaN(indexArr[0]) isNaN(indexArr[0])
? (this.$refs[refName].cycle01 = 0) ? (this.$refs[refName].cycle01 = 0)
: (this.$refs[refName].cycle01 = indexArr[0]); : (this.$refs[refName].cycle01 = indexArr[0])
this.$refs[refName].cycle02 = indexArr[1]; this.$refs[refName].cycle02 = indexArr[1]
insValue = 3; insValue = 3
} else if (value.indexOf("#") > -1) { } else if (value.indexOf("#") > -1) {
let indexArr = value.split("#"); let indexArr = value.split("#")
isNaN(indexArr[0]) isNaN(indexArr[0])
? (this.$refs[refName].average01 = 1) ? (this.$refs[refName].average01 = 1)
: (this.$refs[refName].average01 = indexArr[0]); : (this.$refs[refName].average01 = indexArr[0])
this.$refs[refName].average02 = indexArr[1]; this.$refs[refName].average02 = indexArr[1]
insValue = 4; insValue = 4
} else if (value.indexOf("L") > -1) { } else if (value.indexOf("L") > -1) {
let indexArr = value.split("L"); let indexArr = value.split("L")
isNaN(indexArr[0]) isNaN(indexArr[0])
? (this.$refs[refName].weekday = 1) ? (this.$refs[refName].weekday = 1)
: (this.$refs[refName].weekday = indexArr[0]); : (this.$refs[refName].weekday = indexArr[0])
insValue = 5; insValue = 5
} else { } else {
this.$refs[refName].checkboxList = value.split(","); this.$refs[refName].checkboxList = value.split(",")
insValue = 6; insValue = 6
} }
} else if (name == "year") { } else if (name == "year") {
if (value == "") { if (value == "") {
insValue = 1; insValue = 1
} else if (value == "*") { } else if (value == "*") {
insValue = 2; insValue = 2
} else if (value.indexOf("-") > -1) { } else if (value.indexOf("-") > -1) {
insValue = 3; insValue = 3
} else if (value.indexOf("/") > -1) { } else if (value.indexOf("/") > -1) {
insValue = 4; insValue = 4
} else { } else {
this.$refs[refName].checkboxList = value.split(","); this.$refs[refName].checkboxList = value.split(",")
insValue = 5; insValue = 5
} }
} }
this.$refs[refName].radioValue = insValue; this.$refs[refName].radioValue = insValue
}, },
// 表单选项的子组件校验数字格式(通过-props传递 // 表单选项的子组件校验数字格式(通过-props传递
checkNumber(value, minLimit, maxLimit) { checkNumber(value, minLimit, maxLimit) {
// 检查必须为整数 // 检查必须为整数
value = Math.floor(value); value = Math.floor(value)
if (value < minLimit) { if (value < minLimit) {
value = minLimit; value = minLimit
} else if (value > maxLimit) { } else if (value > maxLimit) {
value = maxLimit; value = maxLimit
} }
return value; return value
}, },
// 隐藏弹窗 // 隐藏弹窗
hidePopup() { hidePopup() {
this.$emit("hide"); this.$emit("hide")
}, },
// 填充表达式 // 填充表达式
submitFill() { submitFill() {
this.$emit("fill", this.crontabValueString); this.$emit("fill", this.crontabValueString)
this.hidePopup(); this.hidePopup()
}, },
clearCron() { clearCron() {
// 还原选择项 // 还原选择项
("准备还原"); ("准备还原")
this.crontabValueObj = { this.crontabValueObj = {
second: "*", second: "*",
min: "*", min: "*",
@@ -322,15 +322,15 @@ export default {
month: "*", month: "*",
week: "?", week: "?",
year: "", year: "",
}; }
for (let j in this.crontabValueObj) { for (let j in this.crontabValueObj) {
this.changeRadio(j, this.crontabValueObj[j]); this.changeRadio(j, this.crontabValueObj[j])
} }
}, },
}, },
computed: { computed: {
crontabValueString: function() { crontabValueString: function() {
let obj = this.crontabValueObj; let obj = this.crontabValueObj
let str = let str =
obj.second + obj.second +
" " + " " +
@@ -343,8 +343,8 @@ export default {
obj.month + obj.month +
" " + " " +
obj.week + obj.week +
(obj.year == "" ? "" : " " + obj.year); (obj.year == "" ? "" : " " + obj.year)
return str; return str
}, },
}, },
components: { components: {
@@ -364,9 +364,9 @@ export default {
}, },
}, },
mounted: function() { mounted: function() {
this.resolveExp(); this.resolveExp()
}, },
}; }
</script> </script>
<style scoped> <style scoped>
.pop_btn { .pop_btn {

View File

@@ -54,35 +54,35 @@ export default {
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')
} }
}, },
@@ -98,18 +98,18 @@ export default {
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
} }
} }
} }

View File

@@ -53,35 +53,35 @@ export default {
radioChange() { radioChange() {
switch (this.radioValue) { switch (this.radioValue) {
case 1: case 1:
this.$emit('update', 'month', '*'); this.$emit('update', 'month', '*')
break; break
case 2: case 2:
this.$emit('update', 'month', this.cycleTotal); this.$emit('update', 'month', this.cycleTotal)
break; break
case 3: case 3:
this.$emit('update', 'month', this.averageTotal); this.$emit('update', 'month', this.averageTotal)
break; break
case 4: case 4:
this.$emit('update', 'month', this.checkboxString); this.$emit('update', 'month', this.checkboxString)
break; break
} }
}, },
// 周期两个值变化时 // 周期两个值变化时
cycleChange() { cycleChange() {
if (this.radioValue == '2') { if (this.radioValue == '2') {
this.$emit('update', 'month', this.cycleTotal); this.$emit('update', 'month', this.cycleTotal)
} }
}, },
// 平均两个值变化时 // 平均两个值变化时
averageChange() { averageChange() {
if (this.radioValue == '3') { if (this.radioValue == '3') {
this.$emit('update', 'month', this.averageTotal); this.$emit('update', 'month', this.averageTotal)
} }
}, },
// checkbox值变化时 // checkbox值变化时
checkboxChange() { checkboxChange() {
if (this.radioValue == '4') { if (this.radioValue == '4') {
this.$emit('update', 'month', this.checkboxString); this.$emit('update', 'month', this.checkboxString)
} }
} }
}, },
@@ -96,18 +96,18 @@ export default {
cycleTotal: function () { cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 1, 11) const cycle01 = this.checkNum(this.cycle01, 1, 11)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12) const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12)
return cycle01 + '-' + cycle02; return cycle01 + '-' + cycle02
}, },
// 计算平均用到的值 // 计算平均用到的值
averageTotal: function () { averageTotal: function () {
const average01 = this.checkNum(this.average01, 1, 11) const average01 = this.checkNum(this.average01, 1, 11)
const average02 = this.checkNum(this.average02, 1, 12 - average01 || 0) const average02 = this.checkNum(this.average02, 1, 12 - 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
} }
} }
} }

View File

@@ -27,135 +27,135 @@ export default {
expressionChange() { expressionChange() {
// 计算开始-隐藏结果 // 计算开始-隐藏结果
this.isShow = false; this.isShow = false
// 获取规则数组[0秒、1分、2时、3日、4月、5星期、6年] // 获取规则数组[0秒、1分、2时、3日、4月、5星期、6年]
let ruleArr = this.$options.propsData.ex.split(' '); let ruleArr = this.$options.propsData.ex.split(' ')
// 用于记录进入循环的次数 // 用于记录进入循环的次数
let nums = 0; let nums = 0
// 用于暂时存符号时间规则结果的数组 // 用于暂时存符号时间规则结果的数组
let resultArr = []; let resultArr = []
// 获取当前时间精确至[年、月、日、时、分、秒] // 获取当前时间精确至[年、月、日、时、分、秒]
let nTime = new Date(); let nTime = new Date()
let nYear = nTime.getFullYear(); let nYear = nTime.getFullYear()
let nMonth = nTime.getMonth() + 1; let nMonth = nTime.getMonth() + 1
let nDay = nTime.getDate(); let nDay = nTime.getDate()
let nHour = nTime.getHours(); let nHour = nTime.getHours()
let nMin = nTime.getMinutes(); let nMin = nTime.getMinutes()
let nSecond = nTime.getSeconds(); let nSecond = nTime.getSeconds()
// 根据规则获取到近100年可能年数组、月数组等等 // 根据规则获取到近100年可能年数组、月数组等等
this.getSecondArr(ruleArr[0]); this.getSecondArr(ruleArr[0])
this.getMinArr(ruleArr[1]); this.getMinArr(ruleArr[1])
this.getHourArr(ruleArr[2]); this.getHourArr(ruleArr[2])
this.getDayArr(ruleArr[3]); this.getDayArr(ruleArr[3])
this.getMonthArr(ruleArr[4]); this.getMonthArr(ruleArr[4])
this.getWeekArr(ruleArr[5]); this.getWeekArr(ruleArr[5])
this.getYearArr(ruleArr[6], nYear); this.getYearArr(ruleArr[6], nYear)
// 将获取到的数组赋值-方便使用 // 将获取到的数组赋值-方便使用
let sDate = this.dateArr[0]; let sDate = this.dateArr[0]
let mDate = this.dateArr[1]; let mDate = this.dateArr[1]
let hDate = this.dateArr[2]; let hDate = this.dateArr[2]
let DDate = this.dateArr[3]; let DDate = this.dateArr[3]
let MDate = this.dateArr[4]; let MDate = this.dateArr[4]
let YDate = this.dateArr[5]; let YDate = this.dateArr[5]
// 获取当前时间在数组中的索引 // 获取当前时间在数组中的索引
let sIdx = this.getIndex(sDate, nSecond); let sIdx = this.getIndex(sDate, nSecond)
let mIdx = this.getIndex(mDate, nMin); let mIdx = this.getIndex(mDate, nMin)
let hIdx = this.getIndex(hDate, nHour); let hIdx = this.getIndex(hDate, nHour)
let DIdx = this.getIndex(DDate, nDay); let DIdx = this.getIndex(DDate, nDay)
let MIdx = this.getIndex(MDate, nMonth); let MIdx = this.getIndex(MDate, nMonth)
let YIdx = this.getIndex(YDate, nYear); let YIdx = this.getIndex(YDate, nYear)
// 重置月日时分秒的函数(后面用的比较多) // 重置月日时分秒的函数(后面用的比较多)
const resetSecond = function () { const resetSecond = function () {
sIdx = 0; sIdx = 0
nSecond = sDate[sIdx] nSecond = sDate[sIdx]
} }
const resetMin = function () { const resetMin = function () {
mIdx = 0; mIdx = 0
nMin = mDate[mIdx] nMin = mDate[mIdx]
resetSecond(); resetSecond()
} }
const resetHour = function () { const resetHour = function () {
hIdx = 0; hIdx = 0
nHour = hDate[hIdx] nHour = hDate[hIdx]
resetMin(); resetMin()
} }
const resetDay = function () { const resetDay = function () {
DIdx = 0; DIdx = 0
nDay = DDate[DIdx] nDay = DDate[DIdx]
resetHour(); resetHour()
} }
const resetMonth = function () { const resetMonth = function () {
MIdx = 0; MIdx = 0
nMonth = MDate[MIdx] nMonth = MDate[MIdx]
resetDay(); resetDay()
} }
// 如果当前年份不为数组中当前值 // 如果当前年份不为数组中当前值
if (nYear !== YDate[YIdx]) { if (nYear !== YDate[YIdx]) {
resetMonth(); resetMonth()
} }
// 如果当前月份不为数组中当前值 // 如果当前月份不为数组中当前值
if (nMonth !== MDate[MIdx]) { if (nMonth !== MDate[MIdx]) {
resetDay(); resetDay()
} }
// 如果当前“日”不为数组中当前值 // 如果当前“日”不为数组中当前值
if (nDay !== DDate[DIdx]) { if (nDay !== DDate[DIdx]) {
resetHour(); resetHour()
} }
// 如果当前“时”不为数组中当前值 // 如果当前“时”不为数组中当前值
if (nHour !== hDate[hIdx]) { if (nHour !== hDate[hIdx]) {
resetMin(); resetMin()
} }
// 如果当前“分”不为数组中当前值 // 如果当前“分”不为数组中当前值
if (nMin !== mDate[mIdx]) { if (nMin !== mDate[mIdx]) {
resetSecond(); resetSecond()
} }
// 循环年份数组 // 循环年份数组
goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) { goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {
let YY = YDate[Yi]; let YY = YDate[Yi]
// 如果到达最大值时 // 如果到达最大值时
if (nMonth > MDate[MDate.length - 1]) { if (nMonth > MDate[MDate.length - 1]) {
resetMonth(); resetMonth()
continue; continue
} }
// 循环月份数组 // 循环月份数组
goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) { goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {
// 赋值、方便后面运算 // 赋值、方便后面运算
let MM = MDate[Mi]; let MM = MDate[Mi];
MM = MM < 10 ? '0' + MM : MM; MM = MM < 10 ? '0' + MM : MM
// 如果到达最大值时 // 如果到达最大值时
if (nDay > DDate[DDate.length - 1]) { if (nDay > DDate[DDate.length - 1]) {
resetDay(); resetDay()
if (Mi == MDate.length - 1) { if (Mi == MDate.length - 1) {
resetMonth(); resetMonth()
continue goYear; continue goYear
} }
continue; continue
} }
// 循环日期数组 // 循环日期数组
goDay: for (let Di = DIdx; Di < DDate.length; Di++) { goDay: for (let Di = DIdx; Di < DDate.length; Di++) {
// 赋值、方便后面运算 // 赋值、方便后面运算
let DD = DDate[Di]; let DD = DDate[Di]
let thisDD = DD < 10 ? '0' + DD : DD; let thisDD = DD < 10 ? '0' + DD : DD
// 如果到达最大值时 // 如果到达最大值时
if (nHour > hDate[hDate.length - 1]) { if (nHour > hDate[hDate.length - 1]) {
resetHour(); resetHour()
if (Di == DDate.length - 1) { if (Di == DDate.length - 1) {
resetDay(); resetDay()
if (Mi == MDate.length - 1) { if (Mi == MDate.length - 1) {
resetMonth(); resetMonth()
continue goYear; continue goYear
} }
continue goMonth; continue goMonth
} }
continue; continue
} }
// 判断日期的合法性,不合法的话也是跳出当前循环 // 判断日期的合法性,不合法的话也是跳出当前循环
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && this.dayRule !== 'workDay' && this.dayRule !== 'lastWeek' && this.dayRule !== 'lastDay') { if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && this.dayRule !== 'workDay' && this.dayRule !== 'lastWeek' && this.dayRule !== 'lastDay') {
resetDay(); resetDay()
continue goMonth; continue goMonth
} }
// 如果日期规则中有值时 // 如果日期规则中有值时
if (this.dayRule == 'lastDay') { if (this.dayRule == 'lastDay') {
@@ -163,84 +163,83 @@ export default {
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--; DD--
thisDD = DD < 10 ? '0' + DD : DD
thisDD = DD < 10 ? '0' + DD : DD;
} }
} }
} else if (this.dayRule == 'workDay') { } else if (this.dayRule == 'workDay') {
// 校验并调整如果是2月30号这种日期传进来时需调整至正常月底 // 校验并调整如果是2月30号这种日期传进来时需调整至正常月底
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--; DD--
thisDD = DD < 10 ? '0' + DD : DD; thisDD = DD < 10 ? '0' + DD : DD
} }
} }
// 获取达到条件的日期是星期X // 获取达到条件的日期是星期X
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week'); let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week')
// 当星期日时 // 当星期日时
if (thisWeek == 1) { if (thisWeek == 1) {
// 先找下一个日,并判断是否为月底 // 先找下一个日,并判断是否为月底
DD++; DD++
thisDD = DD < 10 ? '0' + DD : DD; thisDD = DD < 10 ? '0' + DD : DD
// 判断下一日已经不是合法日期 // 判断下一日已经不是合法日期
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD -= 3; DD -= 3
} }
} else if (thisWeek == 7) { } else if (thisWeek == 7) {
// 当星期6时只需判断不是1号就可进行操作 // 当星期6时只需判断不是1号就可进行操作
if (this.dayRuleSup !== 1) { if (this.dayRuleSup !== 1) {
DD--; DD--
} else { } else {
DD += 2; DD += 2
} }
} }
} else if (this.dayRule == 'weekDay') { } else if (this.dayRule == 'weekDay') {
// 如果指定了是星期几 // 如果指定了是星期几
// 获取当前日期是属于星期几 // 获取当前日期是属于星期几
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week'); let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week')
// 校验当前星期是否在星期池dayRuleSup // 校验当前星期是否在星期池dayRuleSup
if (this.dayRuleSup.indexOf(thisWeek) < 0) { if (this.dayRuleSup.indexOf(thisWeek) < 0) {
// 如果到达最大值时 // 如果到达最大值时
if (Di == DDate.length - 1) { if (Di == DDate.length - 1) {
resetDay(); resetDay()
if (Mi == MDate.length - 1) { if (Mi == MDate.length - 1) {
resetMonth(); resetMonth()
continue goYear; continue goYear
} }
continue goMonth; continue goMonth
} }
continue; continue
} }
} else if (this.dayRule == 'assWeek') { } else if (this.dayRule == 'assWeek') {
// 如果指定了是第几周的星期几 // 如果指定了是第几周的星期几
// 获取每月1号是属于星期几 // 获取每月1号是属于星期几
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week'); let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week')
if (this.dayRuleSup[1] >= thisWeek) { if (this.dayRuleSup[1] >= thisWeek) {
DD = (this.dayRuleSup[0] - 1) * 7 + this.dayRuleSup[1] - thisWeek + 1; DD = (this.dayRuleSup[0] - 1) * 7 + this.dayRuleSup[1] - thisWeek + 1
} else { } else {
DD = this.dayRuleSup[0] * 7 + this.dayRuleSup[1] - thisWeek + 1; DD = this.dayRuleSup[0] * 7 + this.dayRuleSup[1] - thisWeek + 1
} }
} else if (this.dayRule == 'lastWeek') { } else if (this.dayRule == 'lastWeek') {
// 如果指定了每月最后一个星期几 // 如果指定了每月最后一个星期几
// 校验并调整如果是2月30号这种日期传进来时需调整至正常月底 // 校验并调整如果是2月30号这种日期传进来时需调整至正常月底
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--; DD--
thisDD = DD < 10 ? '0' + DD : DD; thisDD = DD < 10 ? '0' + DD : DD
} }
} }
// 获取月末最后一天是星期几 // 获取月末最后一天是星期几
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week'); let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week')
// 找到要求中最近的那个星期几 // 找到要求中最近的那个星期几
if (this.dayRuleSup < thisWeek) { if (this.dayRuleSup < thisWeek) {
DD -= thisWeek - this.dayRuleSup; DD -= thisWeek - this.dayRuleSup
} else if (this.dayRuleSup > thisWeek) { } else if (this.dayRuleSup > thisWeek) {
DD -= 7 - (this.dayRuleSup - thisWeek) DD -= 7 - (this.dayRuleSup - thisWeek)
} }
} }
// 判断时间值是否小于10置换成“05”这种格式 // 判断时间值是否小于10置换成“05”这种格式
DD = DD < 10 ? '0' + DD : DD; DD = DD < 10 ? '0' + DD : DD
// 循环“时”数组 // 循环“时”数组
goHour: for (let hi = hIdx; hi < hDate.length; hi++) { goHour: for (let hi = hIdx; hi < hDate.length; hi++) {
@@ -248,76 +247,76 @@ export default {
// 如果到达最大值时 // 如果到达最大值时
if (nMin > mDate[mDate.length - 1]) { if (nMin > mDate[mDate.length - 1]) {
resetMin(); resetMin()
if (hi == hDate.length - 1) { if (hi == hDate.length - 1) {
resetHour(); resetHour()
if (Di == DDate.length - 1) { if (Di == DDate.length - 1) {
resetDay(); resetDay()
if (Mi == MDate.length - 1) { if (Mi == MDate.length - 1) {
resetMonth(); resetMonth()
continue goYear; continue goYear
} }
continue goMonth; continue goMonth
} }
continue goDay; continue goDay
} }
continue; continue
} }
// 循环"分"数组 // 循环"分"数组
goMin: for (let mi = mIdx; mi < mDate.length; mi++) { goMin: for (let mi = mIdx; mi < mDate.length; mi++) {
let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi]; let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi]
// 如果到达最大值时 // 如果到达最大值时
if (nSecond > sDate[sDate.length - 1]) { if (nSecond > sDate[sDate.length - 1]) {
resetSecond(); resetSecond()
if (mi == mDate.length - 1) { if (mi == mDate.length - 1) {
resetMin(); resetMin()
if (hi == hDate.length - 1) { if (hi == hDate.length - 1) {
resetHour(); resetHour()
if (Di == DDate.length - 1) { if (Di == DDate.length - 1) {
resetDay(); resetDay()
if (Mi == MDate.length - 1) { if (Mi == MDate.length - 1) {
resetMonth(); resetMonth()
continue goYear; continue goYear
} }
continue goMonth; continue goMonth
} }
continue goDay; continue goDay
} }
continue goHour; continue goHour
} }
continue; continue
} }
// 循环"秒"数组 // 循环"秒"数组
goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) { goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {
let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si]; let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si]
// 添加当前时间(时间合法性在日期循环时已经判断) // 添加当前时间(时间合法性在日期循环时已经判断)
if (MM !== '00' && DD !== '00') { if (MM !== '00' && DD !== '00') {
resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss) resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)
nums++; nums++
} }
// 如果条数满了就退出循环 // 如果条数满了就退出循环
if (nums == 5) break goYear; if (nums == 5) break goYear
// 如果到达最大值时 // 如果到达最大值时
if (si == sDate.length - 1) { if (si == sDate.length - 1) {
resetSecond(); resetSecond()
if (mi == mDate.length - 1) { if (mi == mDate.length - 1) {
resetMin(); resetMin()
if (hi == hDate.length - 1) { if (hi == hDate.length - 1) {
resetHour(); resetHour()
if (Di == DDate.length - 1) { if (Di == DDate.length - 1) {
resetDay(); resetDay()
if (Mi == MDate.length - 1) { if (Mi == MDate.length - 1) {
resetMonth(); resetMonth()
continue goYear; continue goYear
} }
continue goMonth; continue goMonth
} }
continue goDay; continue goDay
} }
continue goHour; continue goHour
} }
continue goMin; continue goMin
} }
} //goSecond } //goSecond
} //goMin } //goMin
@@ -327,33 +326,33 @@ export default {
} }
// 判断100年内的结果条数 // 判断100年内的结果条数
if (resultArr.length == 0) { if (resultArr.length == 0) {
this.resultList = ['没有达到条件的结果!']; this.resultList = ['没有达到条件的结果!']
} else { } else {
this.resultList = resultArr; this.resultList = resultArr
if (resultArr.length !== 5) { if (resultArr.length !== 5) {
this.resultList.push('最近100年内只有上面' + resultArr.length + '条结果!') this.resultList.push('最近100年内只有上面' + resultArr.length + '条结果!')
} }
} }
// 计算完成-显示结果 // 计算完成-显示结果
this.isShow = true; this.isShow = true
}, },
// 用于计算某位数字在数组中的索引 // 用于计算某位数字在数组中的索引
getIndex(arr, value) { getIndex(arr, value) {
if (value <= arr[0] || value > arr[arr.length - 1]) { if (value <= arr[0] || value > arr[arr.length - 1]) {
return 0; return 0
} else { } else {
for (let i = 0; i < arr.length - 1; i++) { for (let i = 0; i < arr.length - 1; i++) {
if (value > arr[i] && value <= arr[i + 1]) { if (value > arr[i] && value <= arr[i + 1]) {
return i + 1; return i + 1
} }
} }
} }
}, },
// 获取"年"数组 // 获取"年"数组
getYearArr(rule, year) { getYearArr(rule, year) {
this.dateArr[5] = this.getOrderArr(year, year + 100); this.dateArr[5] = this.getOrderArr(year, year + 100)
if (rule !== undefined) { if (rule !== undefined) {
if (rule.indexOf('-') >= 0) { if (rule.indexOf('-') >= 0) {
this.dateArr[5] = this.getCycleArr(rule, year + 100, false) this.dateArr[5] = this.getCycleArr(rule, year + 100, false)
@@ -366,7 +365,7 @@ export default {
}, },
// 获取"月"数组 // 获取"月"数组
getMonthArr(rule) { getMonthArr(rule) {
this.dateArr[4] = this.getOrderArr(1, 12); this.dateArr[4] = this.getOrderArr(1, 12)
if (rule.indexOf('-') >= 0) { if (rule.indexOf('-') >= 0) {
this.dateArr[4] = this.getCycleArr(rule, 12, false) this.dateArr[4] = this.getCycleArr(rule, 12, false)
} else if (rule.indexOf('/') >= 0) { } else if (rule.indexOf('/') >= 0) {
@@ -380,58 +379,58 @@ export default {
// 只有当日期规则的两个值均为“”时则表达日期是有选项的 // 只有当日期规则的两个值均为“”时则表达日期是有选项的
if (this.dayRule == '' && this.dayRuleSup == '') { if (this.dayRule == '' && this.dayRuleSup == '') {
if (rule.indexOf('-') >= 0) { if (rule.indexOf('-') >= 0) {
this.dayRule = 'weekDay'; this.dayRule = 'weekDay'
this.dayRuleSup = this.getCycleArr(rule, 7, false) this.dayRuleSup = this.getCycleArr(rule, 7, false)
} else if (rule.indexOf('#') >= 0) { } else if (rule.indexOf('#') >= 0) {
this.dayRule = 'assWeek'; this.dayRule = 'assWeek'
let matchRule = rule.match(/[0-9]{1}/g); let matchRule = rule.match(/[0-9]{1}/g)
this.dayRuleSup = [Number(matchRule[1]), Number(matchRule[0])]; this.dayRuleSup = [Number(matchRule[1]), Number(matchRule[0])]
this.dateArr[3] = [1]; this.dateArr[3] = [1]
if (this.dayRuleSup[1] == 7) { if (this.dayRuleSup[1] == 7) {
this.dayRuleSup[1] = 0; this.dayRuleSup[1] = 0
} }
} else if (rule.indexOf('L') >= 0) { } else if (rule.indexOf('L') >= 0) {
this.dayRule = 'lastWeek'; this.dayRule = 'lastWeek'
this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]); this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0])
this.dateArr[3] = [31]; this.dateArr[3] = [31]
if (this.dayRuleSup == 7) { if (this.dayRuleSup == 7) {
this.dayRuleSup = 0; this.dayRuleSup = 0
} }
} else if (rule !== '*' && rule !== '?') { } else if (rule !== '*' && rule !== '?') {
this.dayRule = 'weekDay'; this.dayRule = 'weekDay'
this.dayRuleSup = this.getAssignArr(rule) this.dayRuleSup = this.getAssignArr(rule)
} }
} }
}, },
// 获取"日"数组-少量为日期规则 // 获取"日"数组-少量为日期规则
getDayArr(rule) { getDayArr(rule) {
this.dateArr[3] = this.getOrderArr(1, 31); this.dateArr[3] = this.getOrderArr(1, 31)
this.dayRule = ''; this.dayRule = ''
this.dayRuleSup = ''; this.dayRuleSup = ''
if (rule.indexOf('-') >= 0) { if (rule.indexOf('-') >= 0) {
this.dateArr[3] = this.getCycleArr(rule, 31, false) this.dateArr[3] = this.getCycleArr(rule, 31, false)
this.dayRuleSup = 'null'; this.dayRuleSup = 'null'
} else if (rule.indexOf('/') >= 0) { } else if (rule.indexOf('/') >= 0) {
this.dateArr[3] = this.getAverageArr(rule, 31) this.dateArr[3] = this.getAverageArr(rule, 31)
this.dayRuleSup = 'null'; this.dayRuleSup = 'null'
} else if (rule.indexOf('W') >= 0) { } else if (rule.indexOf('W') >= 0) {
this.dayRule = 'workDay'; this.dayRule = 'workDay'
this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]); this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0])
this.dateArr[3] = [this.dayRuleSup]; this.dateArr[3] = [this.dayRuleSup]
} else if (rule.indexOf('L') >= 0) { } else if (rule.indexOf('L') >= 0) {
this.dayRule = 'lastDay'; this.dayRule = 'lastDay'
this.dayRuleSup = 'null'; this.dayRuleSup = 'null'
this.dateArr[3] = [31]; this.dateArr[3] = [31]
} else if (rule !== '*' && rule !== '?') { } else if (rule !== '*' && rule !== '?') {
this.dateArr[3] = this.getAssignArr(rule) this.dateArr[3] = this.getAssignArr(rule)
this.dayRuleSup = 'null'; this.dayRuleSup = 'null'
} else if (rule == '*') { } else if (rule == '*') {
this.dayRuleSup = 'null'; this.dayRuleSup = 'null'
} }
}, },
// 获取"时"数组 // 获取"时"数组
getHourArr(rule) { getHourArr(rule) {
this.dateArr[2] = this.getOrderArr(0, 23); this.dateArr[2] = this.getOrderArr(0, 23)
if (rule.indexOf('-') >= 0) { if (rule.indexOf('-') >= 0) {
this.dateArr[2] = this.getCycleArr(rule, 24, true) this.dateArr[2] = this.getCycleArr(rule, 24, true)
} else if (rule.indexOf('/') >= 0) { } else if (rule.indexOf('/') >= 0) {
@@ -442,7 +441,7 @@ export default {
}, },
// 获取"分"数组 // 获取"分"数组
getMinArr(rule) { getMinArr(rule) {
this.dateArr[1] = this.getOrderArr(0, 59); this.dateArr[1] = this.getOrderArr(0, 59)
if (rule.indexOf('-') >= 0) { if (rule.indexOf('-') >= 0) {
this.dateArr[1] = this.getCycleArr(rule, 60, true) this.dateArr[1] = this.getCycleArr(rule, 60, true)
} else if (rule.indexOf('/') >= 0) { } else if (rule.indexOf('/') >= 0) {
@@ -453,7 +452,7 @@ export default {
}, },
// 获取"秒"数组 // 获取"秒"数组
getSecondArr(rule) { getSecondArr(rule) {
this.dateArr[0] = this.getOrderArr(0, 59); this.dateArr[0] = this.getOrderArr(0, 59)
if (rule.indexOf('-') >= 0) { if (rule.indexOf('-') >= 0) {
this.dateArr[0] = this.getCycleArr(rule, 60, true) this.dateArr[0] = this.getCycleArr(rule, 60, true)
} else if (rule.indexOf('/') >= 0) { } else if (rule.indexOf('/') >= 0) {
@@ -464,86 +463,86 @@ export default {
}, },
// 根据传进来的min-max返回一个顺序的数组 // 根据传进来的min-max返回一个顺序的数组
getOrderArr(min, max) { getOrderArr(min, max) {
let arr = []; let arr = []
for (let i = min; i <= max; i++) { for (let i = min; i <= max; i++) {
arr.push(i); arr.push(i)
} }
return arr; return arr
}, },
// 根据规则中指定的零散值返回一个数组 // 根据规则中指定的零散值返回一个数组
getAssignArr(rule) { getAssignArr(rule) {
let arr = []; let arr = []
let assiginArr = rule.split(','); let assiginArr = rule.split(',')
for (let i = 0; i < assiginArr.length; i++) { for (let i = 0; i < assiginArr.length; i++) {
arr[i] = Number(assiginArr[i]) arr[i] = Number(assiginArr[i])
} }
arr.sort(this.compare) arr.sort(this.compare)
return arr; return arr
}, },
// 根据一定算术规则计算返回一个数组 // 根据一定算术规则计算返回一个数组
getAverageArr(rule, limit) { getAverageArr(rule, limit) {
let arr = []; let arr = []
let agArr = rule.split('/'); let agArr = rule.split('/')
let min = Number(agArr[0]); let min = Number(agArr[0])
let step = Number(agArr[1]); let step = Number(agArr[1])
while (min <= limit) { while (min <= limit) {
arr.push(min); arr.push(min)
min += step; min += step
} }
return arr; return arr
}, },
// 根据规则返回一个具有周期性的数组 // 根据规则返回一个具有周期性的数组
getCycleArr(rule, limit, status) { getCycleArr(rule, limit, status) {
// status--表示是否从0开始则从1开始 // status--表示是否从0开始则从1开始
let arr = []; let arr = []
let cycleArr = rule.split('-'); let cycleArr = rule.split('-')
let min = Number(cycleArr[0]); let min = Number(cycleArr[0])
let max = Number(cycleArr[1]); let max = Number(cycleArr[1])
if (min > max) { if (min > max) {
max += limit; max += limit
} }
for (let i = min; i <= max; i++) { for (let i = min; i <= max; i++) {
let add = 0; let add = 0
if (status == false && i % limit == 0) { if (status == false && i % limit == 0) {
add = limit; add = limit
} }
arr.push(Math.round(i % limit + add)) arr.push(Math.round(i % limit + add))
} }
arr.sort(this.compare) arr.sort(this.compare)
return arr; return arr
}, },
// 比较数字大小用于Array.sort // 比较数字大小用于Array.sort
compare(value1, value2) { compare(value1, value2) {
if (value2 - value1 > 0) { if (value2 - value1 > 0) {
return -1; return -1
} else { } else {
return 1; return 1
} }
}, },
// 格式化日期格式如2017-9-19 18:04:33 // 格式化日期格式如2017-9-19 18:04:33
formatDate(value, type) { formatDate(value, type) {
// 计算日期相关值 // 计算日期相关值
let time = typeof value == 'number' ? new Date(value) : value; let time = typeof value == 'number' ? new Date(value) : value
let Y = time.getFullYear(); let Y = time.getFullYear()
let M = time.getMonth() + 1; let M = time.getMonth() + 1
let D = time.getDate(); let D = time.getDate()
let h = time.getHours(); let h = time.getHours()
let m = time.getMinutes(); let m = time.getMinutes()
let s = time.getSeconds(); let s = time.getSeconds()
let week = time.getDay(); let week = time.getDay()
// 如果传递了type的话 // 如果传递了type的话
if (type == undefined) { if (type == undefined) {
return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s); return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s)
} else if (type == 'week') { } else if (type == 'week') {
// 在quartz中 1为星期日 // 在quartz中 1为星期日
return week + 1; return week + 1
} }
}, },
// 检查日期是否存在 // 检查日期是否存在
checkDate(value) { checkDate(value) {
let time = new Date(value); let time = new Date(value)
let format = this.formatDate(time) let format = this.formatDate(time)
return value === format; return value === format
} }
}, },
watch: { watch: {
@@ -552,7 +551,7 @@ export default {
props: ['ex'], props: ['ex'],
mounted: function () { mounted: function () {
// 初始化 获取一次结果 // 初始化 获取一次结果
this.expressionChange(); this.expressionChange()
} }
} }

View File

@@ -53,35 +53,35 @@ export default {
radioChange() { radioChange() {
switch (this.radioValue) { switch (this.radioValue) {
case 1: case 1:
this.$emit('update', 'second', '*', 'second'); this.$emit('update', 'second', '*', 'second')
break; break
case 2: case 2:
this.$emit('update', 'second', this.cycleTotal); this.$emit('update', 'second', this.cycleTotal)
break; break
case 3: case 3:
this.$emit('update', 'second', this.averageTotal); this.$emit('update', 'second', this.averageTotal)
break; break
case 4: case 4:
this.$emit('update', 'second', this.checkboxString); this.$emit('update', 'second', this.checkboxString)
break; break
} }
}, },
// 周期两个值变化时 // 周期两个值变化时
cycleChange() { cycleChange() {
if (this.radioValue == '2') { if (this.radioValue == '2') {
this.$emit('update', 'second', this.cycleTotal); this.$emit('update', 'second', this.cycleTotal)
} }
}, },
// 平均两个值变化时 // 平均两个值变化时
averageChange() { averageChange() {
if (this.radioValue == '3') { if (this.radioValue == '3') {
this.$emit('update', 'second', this.averageTotal); this.$emit('update', 'second', this.averageTotal)
} }
}, },
// checkbox值变化时 // checkbox值变化时
checkboxChange() { checkboxChange() {
if (this.radioValue == '4') { if (this.radioValue == '4') {
this.$emit('update', 'second', this.checkboxString); this.$emit('update', 'second', this.checkboxString)
} }
} }
}, },
@@ -99,18 +99,18 @@ export default {
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
} }
} }
} }

View File

@@ -118,52 +118,52 @@ export default {
// 单选按钮值变化时 // 单选按钮值变化时
radioChange() { radioChange() {
if (this.radioValue !== 2 && this.cron.day !== '?') { if (this.radioValue !== 2 && this.cron.day !== '?') {
this.$emit('update', 'day', '?', 'week'); this.$emit('update', 'day', '?', 'week')
} }
switch (this.radioValue) { switch (this.radioValue) {
case 1: case 1:
this.$emit('update', 'week', '*'); this.$emit('update', 'week', '*')
break; break
case 2: case 2:
this.$emit('update', 'week', '?'); this.$emit('update', 'week', '?')
break; break
case 3: case 3:
this.$emit('update', 'week', this.cycleTotal); this.$emit('update', 'week', this.cycleTotal)
break; break
case 4: case 4:
this.$emit('update', 'week', this.averageTotal); this.$emit('update', 'week', this.averageTotal)
break; break
case 5: case 5:
this.$emit('update', 'week', this.weekdayCheck + 'L'); this.$emit('update', 'week', this.weekdayCheck + 'L')
break; break
case 6: case 6:
this.$emit('update', 'week', this.checkboxString); this.$emit('update', 'week', this.checkboxString)
break; break
} }
}, },
// 周期两个值变化时 // 周期两个值变化时
cycleChange() { cycleChange() {
if (this.radioValue == '3') { if (this.radioValue == '3') {
this.$emit('update', 'week', this.cycleTotal); this.$emit('update', 'week', this.cycleTotal)
} }
}, },
// 平均两个值变化时 // 平均两个值变化时
averageChange() { averageChange() {
if (this.radioValue == '4') { if (this.radioValue == '4') {
this.$emit('update', 'week', this.averageTotal); this.$emit('update', 'week', this.averageTotal)
} }
}, },
// 最近工作日值变化时 // 最近工作日值变化时
weekdayChange() { weekdayChange() {
if (this.radioValue == '5') { if (this.radioValue == '5') {
this.$emit('update', 'week', this.weekday + 'L'); this.$emit('update', 'week', this.weekday + 'L')
} }
}, },
// checkbox值变化时 // checkbox值变化时
checkboxChange() { checkboxChange() {
if (this.radioValue == '6') { if (this.radioValue == '6') {
this.$emit('update', 'week', this.checkboxString); this.$emit('update', 'week', this.checkboxString)
} }
}, },
}, },
@@ -179,23 +179,23 @@ export default {
cycleTotal: function () { cycleTotal: function () {
this.cycle01 = this.checkNum(this.cycle01, 1, 7) this.cycle01 = this.checkNum(this.cycle01, 1, 7)
this.cycle02 = this.checkNum(this.cycle02, 1, 7) this.cycle02 = this.checkNum(this.cycle02, 1, 7)
return this.cycle01 + '-' + this.cycle02; return this.cycle01 + '-' + this.cycle02
}, },
// 计算平均用到的值 // 计算平均用到的值
averageTotal: function () { averageTotal: function () {
this.average01 = this.checkNum(this.average01, 1, 4) this.average01 = this.checkNum(this.average01, 1, 4)
this.average02 = this.checkNum(this.average02, 1, 7) this.average02 = this.checkNum(this.average02, 1, 7)
return this.average02 + '#' + this.average01; return this.average02 + '#' + this.average01
}, },
// 最近的工作日(格式) // 最近的工作日(格式)
weekdayCheck: function () { weekdayCheck: function () {
this.weekday = this.checkNum(this.weekday, 1, 7) this.weekday = this.checkNum(this.weekday, 1, 7)
return this.weekday; return this.weekday
}, },
// 计算勾选的checkbox值合集 // 计算勾选的checkbox值合集
checkboxString: function () { checkboxString: function () {
let str = this.checkboxList.join(); let str = this.checkboxList.join()
return str == '' ? '*' : str; return str == '' ? '*' : str
} }
} }
} }

View File

@@ -61,38 +61,38 @@ export default {
radioChange() { radioChange() {
switch (this.radioValue) { switch (this.radioValue) {
case 1: case 1:
this.$emit('update', 'year', ''); this.$emit('update', 'year', '')
break; break
case 2: case 2:
this.$emit('update', 'year', '*'); this.$emit('update', 'year', '*')
break; break
case 3: case 3:
this.$emit('update', 'year', this.cycleTotal); this.$emit('update', 'year', this.cycleTotal)
break; break
case 4: case 4:
this.$emit('update', 'year', this.averageTotal); this.$emit('update', 'year', this.averageTotal)
break; break
case 5: case 5:
this.$emit('update', 'year', this.checkboxString); this.$emit('update', 'year', this.checkboxString)
break; break
} }
}, },
// 周期两个值变化时 // 周期两个值变化时
cycleChange() { cycleChange() {
if (this.radioValue == '3') { if (this.radioValue == '3') {
this.$emit('update', 'year', this.cycleTotal); this.$emit('update', 'year', this.cycleTotal)
} }
}, },
// 平均两个值变化时 // 平均两个值变化时
averageChange() { averageChange() {
if (this.radioValue == '4') { if (this.radioValue == '4') {
this.$emit('update', 'year', this.averageTotal); this.$emit('update', 'year', this.averageTotal)
} }
}, },
// checkbox值变化时 // checkbox值变化时
checkboxChange() { checkboxChange() {
if (this.radioValue == '5') { if (this.radioValue == '5') {
this.$emit('update', 'year', this.checkboxString); this.$emit('update', 'year', this.checkboxString)
} }
} }
}, },
@@ -107,23 +107,23 @@ export default {
cycleTotal: function () { cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098) const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099) const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099)
return cycle01 + '-' + cycle02; return cycle01 + '-' + cycle02
}, },
// 计算平均用到的值 // 计算平均用到的值
averageTotal: function () { averageTotal: function () {
const average01 = this.checkNum(this.average01, this.fullYear, 2098) const average01 = this.checkNum(this.average01, this.fullYear, 2098)
const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear) const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear)
return average01 + '/' + average02; return average01 + '/' + average02
}, },
// 计算勾选的checkbox值合集 // 计算勾选的checkbox值合集
checkboxString: function () { checkboxString: function () {
let str = this.checkboxList.join(); let str = this.checkboxList.join()
return str; return str
} }
}, },
mounted: function () { mounted: function () {
// 仅获取当前年份 // 仅获取当前年份
this.fullYear = Number(new Date().getFullYear()); this.fullYear = Number(new Date().getFullYear())
this.cycle01 = this.fullYear this.cycle01 = this.fullYear
this.average01 = this.fullYear this.average01 = this.fullYear
} }

View File

@@ -74,13 +74,13 @@ export default {
}, },
filters: { filters: {
handleArray(array) { handleArray(array) {
if (array.length === 0) return ''; if (array.length === 0) return ''
return array.reduce((pre, cur) => { return array.reduce((pre, cur) => {
return pre + ' ' + cur; return pre + ' ' + cur
}) })
}, },
} }
}; }
</script> </script>
<style scoped> <style scoped>
.el-tag + .el-tag { .el-tag + .el-tag {

View File

@@ -18,11 +18,12 @@
</template> </template>
<script> <script>
import Quill from "quill"; import axios from "axios"
import "quill/dist/quill.core.css"; import Quill from "quill"
import "quill/dist/quill.snow.css"; import "quill/dist/quill.core.css"
import "quill/dist/quill.bubble.css"; import "quill/dist/quill.snow.css"
import { getToken } from "@/utils/auth"; import "quill/dist/quill.bubble.css"
import { getToken } from "@/utils/auth"
export default { export default {
name: "Editor", name: "Editor",
@@ -88,27 +89,27 @@ export default {
placeholder: "请输入内容", placeholder: "请输入内容",
readOnly: this.readOnly, readOnly: this.readOnly,
}, },
}; }
}, },
computed: { computed: {
styles() { styles() {
let style = {}; let style = {}
if (this.minHeight) { if (this.minHeight) {
style.minHeight = `${this.minHeight}px`; style.minHeight = `${this.minHeight}px`
} }
if (this.height) { if (this.height) {
style.height = `${this.height}px`; style.height = `${this.height}px`
} }
return style; return style
}, }
}, },
watch: { watch: {
value: { value: {
handler(val) { handler(val) {
if (val !== this.currentValue) { if (val !== this.currentValue) {
this.currentValue = val === null ? "" : val; this.currentValue = val === null ? "" : val
if (this.Quill) { if (this.Quill) {
this.Quill.clipboard.dangerouslyPasteHTML(this.currentValue); this.Quill.clipboard.dangerouslyPasteHTML(this.currentValue)
} }
} }
}, },
@@ -116,84 +117,106 @@ export default {
}, },
}, },
mounted() { mounted() {
this.init(); this.init()
}, },
beforeDestroy() { beforeDestroy() {
this.Quill = null; this.Quill = null
}, },
methods: { methods: {
init() { init() {
const editor = this.$refs.editor; const editor = this.$refs.editor
this.Quill = new Quill(editor, this.options); this.Quill = new Quill(editor, this.options)
// 如果设置了上传地址则自定义图片上传事件 // 如果设置了上传地址则自定义图片上传事件
if (this.type == 'url') { if (this.type == 'url') {
let toolbar = this.Quill.getModule("toolbar"); let toolbar = this.Quill.getModule("toolbar")
toolbar.addHandler("image", (value) => { toolbar.addHandler("image", (value) => {
if (value) { if (value) {
this.$refs.upload.$children[0].$refs.input.click(); this.$refs.upload.$children[0].$refs.input.click()
} else { } else {
this.quill.format("image", false); this.quill.format("image", false)
} }
}); })
this.Quill.root.addEventListener('paste', this.handlePasteCapture, true)
} }
this.Quill.clipboard.dangerouslyPasteHTML(this.currentValue); this.Quill.clipboard.dangerouslyPasteHTML(this.currentValue)
this.Quill.on("text-change", (delta, oldDelta, source) => { this.Quill.on("text-change", (delta, oldDelta, source) => {
const html = this.$refs.editor.children[0].innerHTML; const html = this.$refs.editor.children[0].innerHTML
const text = this.Quill.getText(); const text = this.Quill.getText()
const quill = this.Quill; const quill = this.Quill
this.currentValue = html; this.currentValue = html
this.$emit("input", html); this.$emit("input", html)
this.$emit("on-change", { html, text, quill }); this.$emit("on-change", { html, text, quill })
}); })
this.Quill.on("text-change", (delta, oldDelta, source) => { this.Quill.on("text-change", (delta, oldDelta, source) => {
this.$emit("on-text-change", delta, oldDelta, source); this.$emit("on-text-change", delta, oldDelta, source)
}); })
this.Quill.on("selection-change", (range, oldRange, source) => { this.Quill.on("selection-change", (range, oldRange, source) => {
this.$emit("on-selection-change", range, oldRange, source); this.$emit("on-selection-change", range, oldRange, source)
}); })
this.Quill.on("editor-change", (eventName, ...args) => { this.Quill.on("editor-change", (eventName, ...args) => {
this.$emit("on-editor-change", eventName, ...args); this.$emit("on-editor-change", eventName, ...args)
}); })
}, },
// 上传前校检格式和大小 // 上传前校检格式和大小
handleBeforeUpload(file) { handleBeforeUpload(file) {
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]; const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]
const isJPG = type.includes(file.type); const isJPG = type.includes(file.type)
// 检验文件格式 // 检验文件格式
if (!isJPG) { if (!isJPG) {
this.$message.error(`图片格式错误!`); this.$message.error(`图片格式错误!`)
return false; return false
} }
// 校检文件大小 // 校检文件大小
if (this.fileSize) { if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize; const isLt = file.size / 1024 / 1024 < this.fileSize
if (!isLt) { if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`); this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
return false; return false
} }
} }
return true; return true
}, },
handleUploadSuccess(res, file) { handleUploadSuccess(res, file) {
// 如果上传成功 // 如果上传成功
if (res.code == 200) { if (res.code == 200) {
// 获取富文本组件实例 // 获取富文本组件实例
let quill = this.Quill; let quill = this.Quill
// 获取光标所在位置 // 获取光标所在位置
let length = quill.getSelection().index; let length = quill.getSelection().index
// 插入图片 res.url为服务器返回的图片地址 // 插入图片 res.url为服务器返回的图片地址
quill.insertEmbed(length, "image", res.data.url); quill.insertEmbed(length, "image", res.data.url)
// 调整光标到最后 // 调整光标到最后
quill.setSelection(length + 1); quill.setSelection(length + 1)
} else { } else {
this.$message.error("图片插入失败"); this.$message.error("图片插入失败")
} }
}, },
handleUploadError() { handleUploadError() {
this.$message.error("图片插入失败"); this.$message.error("图片插入失败")
}, },
}, // 复制粘贴图片处理
}; handlePasteCapture(e) {
const clipboard = e.clipboardData || window.clipboardData
if (clipboard && clipboard.items) {
for (let i = 0; i < clipboard.items.length; i++) {
const item = clipboard.items[i]
if (item.type.indexOf('image') !== -1) {
e.preventDefault()
const file = item.getAsFile()
this.insertImage(file)
}
}
}
},
insertImage(file) {
const formData = new FormData()
formData.append("file", file)
axios.post(this.uploadUrl, formData, { headers: { "Content-Type": "multipart/form-data", Authorization: this.headers.Authorization } }).then(res => {
this.handleUploadSuccess(res.data)
})
}
}
}
</script> </script>
<style> <style>

View File

@@ -5,6 +5,7 @@
:action="uploadFileUrl" :action="uploadFileUrl"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:file-list="fileList" :file-list="fileList"
:data="data"
:limit="limit" :limit="limit"
:on-error="handleUploadError" :on-error="handleUploadError"
:on-exceed="handleExceed" :on-exceed="handleExceed"
@@ -13,6 +14,7 @@
:headers="headers" :headers="headers"
class="upload-file-uploader" class="upload-file-uploader"
ref="fileUpload" ref="fileUpload"
v-if="!disabled"
> >
<!-- 上传按钮 --> <!-- 上传按钮 -->
<el-button size="mini" type="primary">选取文件</el-button> <el-button size="mini" type="primary">选取文件</el-button>
@@ -26,13 +28,13 @@
</el-upload> </el-upload>
<!-- 文件列表 --> <!-- 文件列表 -->
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"> <transition-group ref="uploadFileList" class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
<li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList"> <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
<el-link :href="file.url" :underline="false" target="_blank"> <el-link :href="file.url" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.name) }} </span> <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link> </el-link>
<div class="ele-upload-list__item-content-action"> <div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link> <el-link :underline="false" @click="handleDelete(index)" type="danger" v-if="!disabled">删除</el-link>
</div> </div>
</li> </li>
</transition-group> </transition-group>
@@ -40,63 +42,98 @@
</template> </template>
<script> <script>
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth"
import Sortable from 'sortablejs'
export default { export default {
name: "FileUpload", name: "FileUpload",
props: { props: {
// 值 // 值
value: [String, Object, Array], value: [String, Object, Array],
// 上传接口地址
action: {
type: String,
default: "/file/upload"
},
// 上传携带的参数
data: {
type: Object
},
// 数量限制 // 数量限制
limit: { limit: {
type: Number, type: Number,
default: 5, default: 5
}, },
// 大小限制(MB) // 大小限制(MB)
fileSize: { fileSize: {
type: Number, type: Number,
default: 5, default: 5
}, },
// 文件类型, 例如['png', 'jpg', 'jpeg'] // 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: { fileType: {
type: Array, type: Array,
default: () => ["doc", "xls", "ppt", "txt", "pdf"], default: () => ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf"]
}, },
// 是否显示提示 // 是否显示提示
isShowTip: { isShowTip: {
type: Boolean, type: Boolean,
default: true default: true
},
// 禁用组件(仅查看文件)
disabled: {
type: Boolean,
default: false
},
// 拖动排序
drag: {
type: Boolean,
default: true
} }
}, },
data() { data() {
return { return {
number: 0, number: 0,
uploadList: [], uploadList: [],
uploadFileUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传文件服务器地址 uploadFileUrl: process.env.VUE_APP_BASE_API + this.action, // 上传文件服务器地址
headers: { headers: {
Authorization: "Bearer " + getToken(), Authorization: "Bearer " + getToken(),
}, },
fileList: [], fileList: []
}; }
},
mounted() {
if (this.drag && !this.disabled) {
this.$nextTick(() => {
const element = this.$refs.uploadFileList?.$el || this.$refs.uploadFileList
Sortable.create(element, {
ghostClass: 'file-upload-darg',
onEnd: (evt) => {
const movedItem = this.fileList.splice(evt.oldIndex, 1)[0]
this.fileList.splice(evt.newIndex, 0, movedItem)
this.$emit("input", this.listToString(this.fileList))
}
})
})
}
}, },
watch: { watch: {
value: { value: {
handler(val) { handler(val) {
if (val) { if (val) {
let temp = 1; let temp = 1
// 首先将值转为数组 // 首先将值转为数组
const list = Array.isArray(val) ? val : this.value.split(','); const list = Array.isArray(val) ? val : this.value.split(',')
// 然后将数组转为对象数组 // 然后将数组转为对象数组
this.fileList = list.map(item => { this.fileList = list.map(item => {
if (typeof item === "string") { if (typeof item === "string") {
item = { name: item, url: item }; item = { name: item, url: item }
} }
item.uid = item.uid || new Date().getTime() + temp++; item.uid = item.uid || new Date().getTime() + temp++
return item; return item
}); })
} else { } else {
this.fileList = []; this.fileList = []
return []; return []
} }
}, },
deep: true, deep: true,
@@ -106,7 +143,7 @@ export default {
computed: { computed: {
// 是否显示提示 // 是否显示提示
showTip() { showTip() {
return this.isShowTip && (this.fileType || this.fileSize); return this.isShowTip && (this.fileType || this.fileSize)
}, },
}, },
methods: { methods: {
@@ -114,91 +151,95 @@ export default {
handleBeforeUpload(file) { handleBeforeUpload(file) {
// 校检文件类型 // 校检文件类型
if (this.fileType) { if (this.fileType) {
const fileName = file.name.split('.'); const fileName = file.name.split('.')
const fileExt = fileName[fileName.length - 1]; const fileExt = fileName[fileName.length - 1]
const isTypeOk = this.fileType.indexOf(fileExt) >= 0; const isTypeOk = this.fileType.indexOf(fileExt) >= 0
if (!isTypeOk) { if (!isTypeOk) {
this.$modal.msgError(`文件格式不正确,请上传${this.fileType.join("/")}格式文件!`); this.$modal.msgError(`文件格式不正确,请上传${this.fileType.join("/")}格式文件!`)
return false; return false
} }
} }
// 校检文件名是否包含特殊字符 // 校检文件名是否包含特殊字符
if (file.name.includes(',')) { if (file.name.includes(',')) {
this.$modal.msgError('文件名不正确,不能包含英文逗号!'); this.$modal.msgError('文件名不正确,不能包含英文逗号!')
return false; return false
} }
// 校检文件大小 // 校检文件大小
if (this.fileSize) { if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize; const isLt = file.size / 1024 / 1024 < this.fileSize
if (!isLt) { if (!isLt) {
this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`); this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`)
return false; return false
} }
} }
this.$modal.loading("正在上传文件,请稍候..."); this.$modal.loading("正在上传文件,请稍候...")
this.number++; this.number++
return true; return true
}, },
// 文件个数超出 // 文件个数超出
handleExceed() { handleExceed() {
this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`); this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`)
}, },
// 上传失败 // 上传失败
handleUploadError(err) { handleUploadError(err) {
this.$modal.msgError("上传文件失败,请重试"); this.$modal.msgError("上传文件失败,请重试")
this.$modal.closeLoading() this.$modal.closeLoading()
}, },
// 上传成功回调 // 上传成功回调
handleUploadSuccess(res, file) { handleUploadSuccess(res, file) {
if (res.code === 200) { if (res.code === 200) {
this.uploadList.push({ name: res.data.url, url: res.data.url }); this.uploadList.push({ name: res.data.url, url: res.data.url })
this.uploadedSuccessfully(); this.uploadedSuccessfully()
} else { } else {
this.number--; this.number--
this.$modal.closeLoading(); this.$modal.closeLoading()
this.$modal.msgError(res.msg); this.$modal.msgError(res.msg)
this.$refs.fileUpload.handleRemove(file); this.$refs.fileUpload.handleRemove(file)
this.uploadedSuccessfully(); this.uploadedSuccessfully()
} }
}, },
// 删除文件 // 删除文件
handleDelete(index) { handleDelete(index) {
this.fileList.splice(index, 1); this.fileList.splice(index, 1)
this.$emit("input", this.listToString(this.fileList)); this.$emit("input", this.listToString(this.fileList))
}, },
// 上传结束处理 // 上传结束处理
uploadedSuccessfully() { uploadedSuccessfully() {
if (this.number > 0 && this.uploadList.length === this.number) { if (this.number > 0 && this.uploadList.length === this.number) {
this.fileList = this.fileList.concat(this.uploadList); this.fileList = this.fileList.concat(this.uploadList)
this.uploadList = []; this.uploadList = []
this.number = 0; this.number = 0
this.$emit("input", this.listToString(this.fileList)); this.$emit("input", this.listToString(this.fileList))
this.$modal.closeLoading(); this.$modal.closeLoading()
} }
}, },
// 获取文件名称 // 获取文件名称
getFileName(name) { getFileName(name) {
// 如果是url那么取最后的名字 如果不是直接返回 // 如果是url那么取最后的名字 如果不是直接返回
if (name.lastIndexOf("/") > -1) { if (name.lastIndexOf("/") > -1) {
return name.slice(name.lastIndexOf("/") + 1); return name.slice(name.lastIndexOf("/") + 1)
} else { } else {
return name; return name
} }
}, },
// 对象转成指定字符串分隔 // 对象转成指定字符串分隔
listToString(list, separator) { listToString(list, separator) {
let strs = ""; let strs = ""
separator = separator || ","; separator = separator || ","
for (let i in list) { for (let i in list) {
strs += list[i].url + separator; strs += list[i].url + separator
} }
return strs != '' ? strs.substr(0, strs.length - 1) : ''; return strs != '' ? strs.substr(0, strs.length - 1) : ''
} }
} }
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.file-upload-darg {
opacity: 0.5;
background: #c8ebfb;
}
.upload-file-uploader { .upload-file-uploader {
margin-bottom: 5px; margin-bottom: 5px;
} }

View File

@@ -1,27 +1,52 @@
<template> <template>
<div :class="{'show':show}" class="header-search"> <div class="header-search">
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
<el-select <el-dialog
ref="headerSearchSelect" :visible.sync="show"
v-model="search" width="600px"
:remote-method="querySearch" @close="close"
filterable :show-close="false"
default-first-option append-to-body
remote
placeholder="Search"
class="header-search-select"
@change="change"
> >
<el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" /> <el-input
</el-select> v-model="search"
ref="headerSearchSelectRef"
size="large"
@input="querySearch"
prefix-icon="el-icon-search"
placeholder="菜单搜索支持标题、URL模糊查询"
clearable
@keyup.enter.native="selectActiveResult"
@keydown.up.native="navigateResult('up')"
@keydown.down.native="navigateResult('down')"
>
</el-input>
<el-scrollbar wrap-class="right-scrollbar-wrapper">
<div class="result-wrap">
<div class="search-item" v-for="(item, index) in options" :key="item.path" :style="activeStyle(index)" @mouseenter="activeIndex = index" @mouseleave="activeIndex = -1">
<div class="left">
<svg-icon class="menu-icon" :icon-class="item.icon" />
</div>
<div class="search-info" @click="change(item)">
<div class="menu-title">
{{ item.title.join(" / ") }}
</div>
<div class="menu-path">
{{ item.path }}
</div>
</div>
<svg-icon icon-class="enter" v-show="index === activeIndex"/>
</div>
</div>
</el-scrollbar>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
// fuse is a lightweight fuzzy-search module
// make search results more in line with expectations
import Fuse from 'fuse.js/dist/fuse.min.js' import Fuse from 'fuse.js/dist/fuse.min.js'
import path from 'path' import path from 'path'
import { isHttp } from '@/utils/validate'
export default { export default {
name: 'HeaderSearch', name: 'HeaderSearch',
@@ -30,13 +55,17 @@ export default {
search: '', search: '',
options: [], options: [],
searchPool: [], searchPool: [],
activeIndex: -1,
show: false, show: false,
fuse: undefined fuse: undefined
} }
}, },
computed: { computed: {
theme() {
return this.$store.state.settings.theme
},
routes() { routes() {
return this.$store.getters.permission_routes return this.$store.getters.defaultRoutes
} }
}, },
watch: { watch: {
@@ -45,13 +74,6 @@ export default {
}, },
searchPool(list) { searchPool(list) {
this.initFuse(list) this.initFuse(list)
},
show(value) {
if (value) {
document.body.addEventListener('click', this.close)
} else {
document.body.removeEventListener('click', this.close)
}
} }
}, },
mounted() { mounted() {
@@ -62,23 +84,26 @@ export default {
this.show = !this.show this.show = !this.show
if (this.show) { if (this.show) {
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus() this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
this.options = this.searchPool
} }
}, },
close() { close() {
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur() this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
this.search = ''
this.options = [] this.options = []
this.show = false this.show = false
this.activeIndex = -1
}, },
change(val) { change(val) {
const path = val.path; const path = val.path
const query = val.query; const query = val.query
if(this.ishttp(val.path)) { if(isHttp(val.path)) {
// http(s):// 路径新窗口打开 // http(s):// 路径新窗口打开
const pindex = path.indexOf("http"); const pindex = path.indexOf("http")
window.open(path.substr(pindex, path.length), "_blank"); window.open(path.substr(pindex, path.length), "_blank")
} else { } else {
if (query) { if (query) {
this.$router.push({ path: path, query: JSON.parse(query) }); this.$router.push({ path: path, query: JSON.parse(query) })
} else { } else {
this.$router.push(path) this.$router.push(path)
} }
@@ -115,12 +140,14 @@ export default {
if (router.hidden) { continue } if (router.hidden) { continue }
const data = { const data = {
path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path, path: !isHttp(router.path) ? path.resolve(basePath, router.path) : router.path,
title: [...prefixTitle] title: [...prefixTitle],
icon: ''
} }
if (router.meta && router.meta.title) { if (router.meta && router.meta.title) {
data.title = [...data.title, router.meta.title] data.title = [...data.title, router.meta.title]
data.icon = router.meta.icon
if (router.redirect !== 'noRedirect') { if (router.redirect !== 'noRedirect') {
// only push the routes with title // only push the routes with title
@@ -144,55 +171,94 @@ export default {
return res return res
}, },
querySearch(query) { querySearch(query) {
this.activeIndex = -1
if (query !== '') { if (query !== '') {
this.options = this.fuse.search(query) this.options = this.fuse.search(query).map((item) => item.item) ?? this.searchPool
} else { } else {
this.options = [] this.options = this.searchPool
} }
}, },
ishttp(url) { activeStyle(index) {
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 if (index !== this.activeIndex) return {}
return {
"background-color": this.theme,
"color": "#fff"
}
},
navigateResult(direction) {
if (direction === "up") {
this.activeIndex = this.activeIndex <= 0 ? this.options.length - 1 : this.activeIndex - 1
} else if (direction === "down") {
this.activeIndex = this.activeIndex >= this.options.length - 1 ? 0 : this.activeIndex + 1
}
},
selectActiveResult() {
if (this.options.length > 0 && this.activeIndex >= 0) {
this.change(this.options[this.activeIndex])
}
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang='scss' scoped>
.header-search { ::v-deep {
font-size: 0 !important; .el-dialog__header {
padding: 0 !important;
}
}
.header-search {
.search-icon { .search-icon {
cursor: pointer; cursor: pointer;
font-size: 18px; font-size: 18px;
vertical-align: middle; vertical-align: middle;
} }
}
.header-search-select { .result-wrap {
font-size: 18px; height: 280px;
transition: width 0.2s; margin: 6px 0;
width: 0;
overflow: hidden;
background: transparent;
border-radius: 0;
display: inline-block;
vertical-align: middle;
::v-deep .el-input__inner { .search-item {
border-radius: 0; display: flex;
border: 0; height: 48px;
padding-left: 0; align-items: center;
padding-right: 0; padding-right: 10px;
box-shadow: none !important;
border-bottom: 1px solid #d9d9d9; .left {
vertical-align: middle; width: 60px;
text-align: center;
.menu-icon {
width: 18px;
height: 18px;
}
}
.search-info {
padding-left: 5px;
margin-top: 10px;
width: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
flex: 1;
.menu-title,
.menu-path {
height: 20px;
}
.menu-path {
color: #ccc;
font-size: 10px;
}
} }
} }
&.show { .search-item:hover {
.header-search-select { cursor: pointer;
width: 210px;
margin-left: 10px;
}
} }
} }
</style> </style>

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