Commit e325c69c authored by hkl's avatar hkl

Merge branch 'dev-hkl' into 'master'

Dev hkl

See merge request !1
parents 66c23824 accfedad
![JEECG](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/logov3.png "JeecgBoot低代码开发平台")
JEECG BOOT 低代码开发平台
===============
当前最新版本: 3.5.1(发布日期:2023-04-20)
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京敲敲云科技-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.5.1-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
项目介绍
-----------------------------------
<h3 align="center">Java Low Code Platform for Enterprise web applications</h3>
JeecgBoot 是一款基于代码生成器的`低代码开发平台`!前后端分离架构 SpringBoot2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot 引领新的低代码开发模式(OnlineCoding-> 代码生成器-> 手工MERGE), 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省研发成本,同时又不失灵活性!
JeecgBoot 提供了一系列`低代码模块`,实现在线开发`真正的零代码`:Online表单开发、Online报表、报表配置能力、在线图表设计、大屏设计、移动配置能力、表单设计器、在线设计流程、流程自动化配置、插件能力(可插拔)等等!
`JEECG宗旨是:` 简单功能由OnlineCoding配置实现,做到`零代码开发`;复杂功能由代码生成器生成进行手工Merge 实现`低代码开发`,既保证了`智能`又兼顾`灵活`;实现了低代码开发的同时又支持灵活编码,解决了当前低代码产品普遍不灵活的弊端!
`JEECG业务流程:` 采用工作流来实现、扩展出任务接口,供开发编写业务逻辑,表单提供多种解决方案: 表单设计器、online配置表单、编码表单。同时实现了流程与表单的分离设计(松耦合)、并支持任务节点灵活配置,既保证了公司流程的保密性,又减少了开发人员的工作量。
适用项目
-----------------------------------
Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中,尤其适合SAAS项目、企业信息管理系统(MIS)、内部办公系统(OA)、企业资源计划系统(ERP)、客户关系管理系统(CRM)等,其半智能手工Merge的开发方式,可以显著提高开发效率70%以上,极大降低开发成本。
源码下载
-----------------------------------
| 源码 | 源码地址 |
|--------------------|------------------------|
| 后台源码 JAVA | https://github.com/jeecgboot/jeecg-boot |
| 前端源码 `Vue3版` | https://github.com/jeecgboot/jeecgboot-vue3 |
| APP配套框架 | https://github.com/jeecgboot/jeecg-uniapp |
##### 快速搭建开发环境
- [通过IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
- [Vue3前端项目快速启动](http://help.jeecg.com/setup/startup.html)
- [单体快速切换为微服务版](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
##### 项目说明
| 项目名 | 说明 |
|--------------------|------------------------|
| `jeecg-boot` | SpringBoot后台源码(支持微服务) |
| `jeecgboot-vue3` | Vue3+TS 新版前端源码 |
| `jeecg-uniapp` | APP开发框架,一份代码多终端适配,同时支持APP、小程序、H5 |
| `jeecg-boot-starter` | [Stater依赖项目单独维护,点击下载](https://gitee.com/jeecg/jeecg-boot-starter) |
| `更多开源插件` | [更多源码下载](https://github.com/jeecgboot) |
技术支持
-----------------------------------
关闭gitee的issue通道,使用中遇到问题或者BUG可以在 [Github上提Issues](https://github.com/jeecgboot/jeecg-boot/issues/new)
官方支持: [http://jeecg.com/doc/help](http://jeecg.com/doc/help)
技术文档
-----------------------------------
- 项目官网: [http://www.jeecg.com](http://www.jeecg.com)
- 在线演示 : [低代码演示](http://boot3.jeecg.com) | [零代码体验](http://app.qiaoqiaoyun.com)
- 开发文档: [http://help.jeecg.com](http://help.jeecg.com)
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [常见问题 ](http://www.jeecg.com/doc/qa) | [视频教程](https://space.bilibili.com/454617261/channel/series) | [1分钟低代码体验](https://my.oschina.net/jeecg/blog/3083313)
- QQ交流群 : ⑦791696430、⑥730954414、VUE3群683903138、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
> ` 提醒:【QQ群是自助服务群,建议给帮助您解决问题的同学发送指定红包,表示感谢!】 `
Docker启动项目
-----------------------------------
- [Docker启动单体后台](https://help.jeecg.com/java/setup/docker/up.html)
- [Docker启动Vue3前端](http://help.jeecg.com/publish/docker.html)
- [Docker启动微服务后台](https://help.jeecg.com/java/springcloud/docker.html)
=======【VUE2版本专题介绍】============================================
VUE2版本专题介绍
-----------------------------------
#### 项目介绍
- 项目名称:ant-design-vue-jeecg
- 说明:JeecgBoot前端提供两套解决方案,一套VUE2和一套VUE3版本,目前vue2版本最新代码只支持到jeecgboot 3.4.3版本,一定注意。
- 更多介绍:[Vue2版演示](http://boot.jeecg.com) |[开发文档](http://doc.jeecg.com)
- [快速启动——Vue2前端](http://doc.jeecg.com/2678320)
- [Docker启动——Vue2前端](http://doc.jeecg.com/3043612)
#### Vue2与Vue3版本区别
> - VUE3版本彻底抛弃IE兼容,不兼容IE和低版本浏览器,只适配高版本谷歌和Edge
(政府、事业类单位项目需要谨慎选择——国产化迁移是一个漫长的过程,万一过程中要求IE兼容,这个不可逆)
> - 所以如果对浏览器有要求的项目,请选择VUE2版本。
> - VUE3版是全新的技术栈,紧跟主流(前端重写),各个功能都做了优化,拥有更好的体验效果
#### 源码下载
| 源码 | 源码地址 |
|--------------------|------------------------|
| 后端源码 `Vue2版` |https://gitee.com/jeecg/jeecg-boot/tree/v3.4.3last |
| 前端源码 `Vue2版` |https://gitee.com/jeecg/ant-design-vue-jeecg |
=========【VUE2版本专题介绍】=========================================
##### Star走势图
[![Star History Chart](https://api.star-history.com/svg?repos=jeecgboot/jeecg-boot&type=Date)](https://star-history.com/#jeecgboot/jeecg-boot)
后台目录结构
-----------------------------------
```
项目结构
├─jeecg-boot-parent(父POM: 项目依赖、modules组织)
│ ├─jeecg-boot-base-core(共通模块: 工具类、config、权限、查询过滤器、注解等)
│ ├─jeecg-module-demo 示例代码
│ ├─jeecg-module-system System系统管理目录
│ │ ├─jeecg-system-biz System系统管理权限等功能
│ │ ├─jeecg-system-start System单体启动项目(8080)
│ │ ├─jeecg-system-api System系统管理模块对外api
│ │ │ ├─jeecg-system-cloud-api System模块对外提供的微服务接口
│ │ │ ├─jeecg-system-local-api System模块对外提供的单体接口
│ ├─jeecg-server-cloud --微服务模块
├─jeecg-cloud-gateway --微服务网关模块(9999)
├─jeecg-cloud-nacos --Nacos服务模块(8848)
├─jeecg-system-cloud-start --System微服务启动项目(7001)
├─jeecg-demo-cloud-start --Demo微服务启动项目(7002)
├─jeecg-visual
├─jeecg-cloud-monitor --微服务监控模块 (9111)
├─jeecg-cloud-xxljob --微服务xxljob定时任务服务端 (9080)
├─jeecg-cloud-sentinel --sentinel服务端 (9000)
├─jeecg-cloud-test -- 微服务测试示例(各种例子)
├─jeecg-cloud-test-more -- 微服务测试示例(feign、熔断降级、xxljob、分布式锁)
├─jeecg-cloud-test-rabbitmq -- 微服务测试示例(rabbitmq)
├─jeecg-cloud-test-seata -- 微服务测试示例(seata分布式事务)
├─jeecg-cloud-test-shardingsphere -- 微服务测试示例(分库分表)
```
为什么选择JeecgBoot?
-----------------------------------
* 1.采用最新主流前后分离框架(Springboot+Mybatis+antd),容易上手; 代码生成器依赖性低,灵活的扩展能力,可快速实现二次开发;
* 2.支持微服务SpringCloud Alibaba(Nacos、Gateway、Sentinel、Skywalking),提供切换机制支持单体和微服务自由切换
* 3.开发效率高,采用代码生成器,单表、树列表、一对多、一对一等数据模型,增删改查功能一键生成,菜单配置直接使用;
* 4.代码生成器提供强大模板机制,支持自定义模板,目前提供四套风格模板(单表两套、树模型一套、一对多三套)
* 5.代码生成器非常智能,在线业务建模、在线配置、所见即所得支持23种类控件,一键生成前后端代码,大幅度提升开发效率,不再为重复工作发愁。
* 6.低代码能力:Online在线表单(无需编码,通过在线配置表单,实现表单的增删改查,支持单表、树、一对多、一对一等模型,实现人人皆可编码)
* 7.低代码能力:Online在线报表(无需编码,通过在线配置方式,实现数据报表,可以快速抽取数据,减轻开发压力,实现人人皆可编码)
* 8.低代码能力:Online在线图表(无需编码,通过在线配置方式,实现曲线图,柱状图,数据报表等,支持自定义排版布局,实现人人皆可编码)
* 9.封装完善的用户、角色、菜单、组织机构、数据字典、在线定时任务等基础功能,支持访问授权、按钮权限、数据权限等功能
* 10.常用共通封装,各种工具类(定时任务,短信接口,邮件发送,Excel导入导出等),基本满足80%项目需求
* 11.简易Excel导入导出,支持单表导出和一对多表模式导出,生成的代码自带导入导出功能
* 12.集成简易报表工具,图像报表和数据导出非常方便,可极其方便的生成图形报表、pdf、excel、word等报表;
* 13.采用前后分离技术,页面UI风格精美,针对常用组件做了封装:时间、行表格控件、截取显示控件、报表组件,编辑器等等
* 14.查询过滤器:查询功能自动生成,后台动态拼SQL追加查询条件;支持多种匹配方式(全匹配/模糊查询/包含查询/不匹配查询);
* 15.数据权限(精细化数据权限控制,控制到行级,列表级,表单字段级,实现不同人看不同数据,不同人对同一个页面操作不同字段
* 16.页面校验自动生成(必须输入、数字校验、金额校验、时间空间等);
* 17.支持SAAS服务模式,提供SaaS多租户架构方案。
* 18.分布式文件服务,集成minio、阿里OSS等优秀的第三方,提供便捷的文件上传与管理,同时也支持本地存储。
* 19.主流数据库兼容,一套代码完全兼容Mysql、Postgresql、Oracle、Sqlserver、MariaDB、达梦等主流数据库。
* 20.集成工作流activiti、flowable,并实现了只需在页面配置流程转向,可极大的简化bpm工作流的开发;用bpm的流程设计器画出了流程走向,一个工作流基本就完成了,只需写很少量的java代码;
* 21.低代码能力:在线流程设计,采用开源Activiti流程引擎,实现在线画流程,自定义表单,表单挂靠,业务流转
* 22.多数据源:及其简易的使用方式,在线配置数据源配置,便捷的从其他数据抓取数据;
* 23.提供单点登录CAS集成方案,项目中已经提供完善的对接代码
* 24.低代码能力:表单设计器,支持用户自定义表单布局,支持单表,一对多表单、支持select、radio、checkbox、textarea、date、popup、列表、宏等控件
* 25.专业接口对接机制,统一采用restful接口方式,集成swagger-ui在线接口文档,Jwt token安全验证,方便客户端对接
* 26.接口安全机制,可细化控制接口授权,非常简便实现不同客户端只看自己数据等控制
* 27.高级组合查询功能,在线配置支持主子表关联查询,可保存查询历史
* 28.提供各种系统监控,实时跟踪系统运行情况(监控 Redis、Tomcat、jvm、服务器信息、请求追踪、SQL监控)
* 29.消息中心(支持短信、邮件、微信推送等等)
* 30.集成Websocket消息通知机制
* 31.移动自适应效果优秀,提供APP发布方案:
* 32.支持多语言,提供国际化方案;
* 33.数据变更记录日志,可记录数据每次变更内容,通过版本对比功能查看历史变化
* 34.平台UI强大,实现了移动自适应
* 35.平台首页风格,提供多种组合模式,支持自定义风格
* 36.提供简单易用的打印插件,支持谷歌、火狐、IE11+ 等各种浏览器
* 37.示例代码丰富,提供很多学习案例参考
* 38.采用maven分模块开发方式
* 39.支持菜单动态路由
* 40.权限控制采用 RBAC(Role-Based Access Control,基于角色的访问控制)
* 41.提供新行编辑表格JVXETable,轻松满足各种复杂ERP布局,拥有更高的性能、更灵活的扩展、更强大的功能
技术架构:
-----------------------------------
#### 开发环境
- 语言:Java 8+ (小于17)
- IDE(JAVA): IDEA (必须安装lombok插件 )
- IDE(前端): Vscode、WebStorm、IDEA
- 依赖管理:Maven
- 缓存:Redis
- 数据库脚本:MySQL5.7+ & Oracle 11g & Sqlserver2017(其他数据库,[需要自己转](https://my.oschina.net/jeecg/blog/4905722)
#### 后端
- 基础框架:Spring Boot 2.6.14
- 微服务框架: Spring Cloud Alibaba 2021.0.1.0
- 持久层框架:MybatisPlus 3.5.1
- 报表工具: JimuReport 1.5.8
- 安全框架:Apache Shiro 1.10.0,Jwt 3.11.0
- 微服务技术栈:Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking
- 数据库连接池:阿里巴巴Druid 1.1.22
- 日志打印:logback
- 其他:autopoi, fastjson,poi,Swagger-ui,quartz, lombok(简化代码)等。
#### 前端
- Vue2版本:`Vue2.6+@vue/cli+AntDesignVue+Viser-vue+Vuex等` [详细查看](https://github.com/jeecgboot/ant-design-vue-jeecg)
- Vue3版本:`Vue3.0+TypeScript+Vite+AntDesignVue+pinia+echarts等新方案` [详细查看](https://github.com/jeecgboot/jeecgboot-vue3)
#### 支持库
| 数据库 | 支持 |
| --- | --- |
| MySQL | √ |
| Oracle11g | √ |
| Sqlserver2017 | √ |
| PostgreSQL | √ |
| MariaDB | √ |
| 达梦、人大金仓 | √ |
## 微服务解决方案
1、服务注册和发现 Nacos √
2、统一配置中心 Nacos √
3、路由网关 gateway(三种加载方式) √
4、分布式 http feign √
5、熔断降级限流 Sentinel √
6、分布式文件 Minio、阿里OSS √
7、统一权限控制 JWT + Shiro √
8、服务监控 SpringBootAdmin√
9、链路跟踪 Skywalking [参考文档](https://help.jeecg.com/java/springcloud/super/skywarking.html)
10、消息中间件 RabbitMQ √
11、分布式任务 xxl-job √
12、分布式事务 Seata
13、分布式日志 elk + kafka
14、支持 docker-compose、k8s、jenkins
15、CAS 单点登录 √
16、路由限流 √
#### 微服务架构图
![微服务架构图](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/jeecgboot_springcloud2022.png "在这里输入图片标题")
### Jeecg Boot 产品功能蓝图
![功能蓝图](https://jeecgos.oss-cn-beijing.aliyuncs.com/upload/test/Jeecg-Boot-lantu202005_1590912449914.jpg "在这里输入图片标题")
### 功能模块
```
├─系统管理
│ ├─用户管理
│ ├─角色管理
│ ├─菜单管理
│ ├─权限设置(支持按钮权限、数据权限)
│ ├─表单权限(控制字段禁用、隐藏)
│ ├─部门管理
│ ├─我的部门(二级管理员)
│ └─字典管理
│ └─分类字典
│ └─系统公告
│ └─职务管理
│ └─通讯录
│ └─多租户管理
├─消息中心
│ ├─消息管理
│ ├─模板管理
├─代码生成器(低代码)
│ ├─代码生成器功能(一键生成前后端代码,生成后无需修改直接用,绝对是后端开发福音)
│ ├─代码生成器模板(提供4套模板,分别支持单表和一对多模型,不同风格选择)
│ ├─代码生成器模板(生成代码,自带excel导入导出)
│ ├─查询过滤器(查询逻辑无需编码,系统根据页面配置自动生成)
│ ├─高级查询器(弹窗自动组合查询条件)
│ ├─Excel导入导出工具集成(支持单表,一对多 导入导出)
│ ├─平台移动自适应支持
├─系统监控
│ ├─Gateway路由网关
│ ├─性能扫描监控
│ │ ├─监控 Redis
│ │ ├─Tomcat
│ │ ├─jvm
│ │ ├─服务器信息
│ │ ├─请求追踪
│ │ ├─磁盘监控
│ ├─定时任务
│ ├─系统日志
│ ├─消息中心(支持短信、邮件、微信推送等等)
│ ├─数据日志(记录数据快照,可对比快照,查看数据变更情况)
│ ├─系统通知
│ ├─SQL监控
│ ├─swagger-ui(在线接口文档)
│─报表示例
│ ├─曲线图
│ └─饼状图
│ └─柱状图
│ └─折线图
│ └─面积图
│ └─雷达图
│ └─仪表图
│ └─进度条
│ └─排名列表
│ └─等等
│─大屏模板
│ ├─作战指挥中心大屏
│ └─物流服务中心大屏
│─常用示例
│ ├─自定义组件
│ ├─对象存储(对接阿里云)
│ ├─JVXETable示例(各种复杂ERP布局示例)
│ ├─单表模型例子
│ └─一对多模型例子
│ └─打印例子
│ └─一对多TAB例子
│ └─内嵌table例子
│ └─常用选择组件
│ └─异步树table
│ └─接口模拟测试
│ └─表格合计示例
│ └─异步树列表示例
│ └─一对多JEditable
│ └─JEditable组件示例
│ └─图片拖拽排序
│ └─图片翻页
│ └─图片预览
│ └─PDF预览
│ └─分屏功能
│─封装通用组件
│ ├─行编辑表格JEditableTable
│ └─省略显示组件
│ └─时间控件
│ └─高级查询
│ └─用户选择组件
│ └─报表组件封装
│ └─字典组件
│ └─下拉多选组件
│ └─选人组件
│ └─选部门组件
│ └─通过部门选人组件
│ └─封装曲线、柱状图、饼状图、折线图等等报表的组件(经过封装,使用简单)
│ └─在线code编辑器
│ └─上传文件组件
│ └─验证码组件
│ └─树列表组件
│ └─表单禁用组件
│ └─等等
│─更多页面模板
│ ├─各种高级表单
│ ├─各种列表效果
│ └─结果页面
│ └─异常页面
│ └─个人页面
├─高级功能
│ ├─系统编码规则
│ ├─提供单点登录CAS集成方案
│ ├─提供APP发布方案
│ ├─集成Websocket消息通知机制
├─Online在线开发(低代码)
│ ├─Online在线表单 - 功能已开放
│ ├─Online代码生成器 - 功能已开放
│ ├─Online在线报表 - 功能已开放
│ ├─Online在线图表(未开源)
│ ├─Online图表模板配置(未开源)
│ ├─Online布局设计(未开源)
│ ├─多数据源管理 - 功能已开放
├─积木报表设计器(低代码)
│ ├─打印设计器
│ ├─数据报表设计
│ ├─图形报表设计(支持echart)
│ ├─大屏设计器(未开源)
│─更多商业功能 (未开源)
│ ├─流程设计器
│ ├─表单设计器
├─大屏设计器
├─门户设计/仪表盘设计器
│ └─我的任务
│ └─历史流程
│ └─历史流程
│ └─流程实例管理
│ └─流程监听管理
│ └─流程表达式
│ └─我发起的流程
│ └─我的抄送
│ └─流程委派、抄送、跳转
│ └─。。。
│─OA办公组件 (未开源)
│ ├─更多功能
│ └─。。。
└─其他模块
└─更多功能开发中。。
```
### 系统效果
##### PC端
![](https://oscimg.oschina.net/oscnet/up-000530d95df337b43089ac77e562494f454.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14155402_AmlV.png "在这里输入图片标题")
![](https://oscimg.oschina.net/oscnet/up-9d6f36f251e71a0b515a01323474b03004c.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160813_KmXS.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160935_Nibs.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14161004_bxQ4.png "在这里输入图片标题")
##### 系统交互
![](https://oscimg.oschina.net/oscnet/up-78b151fc888d4319377bf1cc311fe826871.png)
![](https://oscimg.oschina.net/oscnet/up-16c07e000278329b69b228ae3189814b8e9.png)
##### 流程设计
![](https://oscimg.oschina.net/oscnet/up-981ce174e4fbb48c8a2ce4ccfd7372e2994.png)
![输入图片说明](https://static.oschina.net/uploads/img/201907/05165142_yyQ7.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160917_9Ftz.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160633_u59G.png "在这里输入图片标题")
##### 简版流程设计
![](https://oscimg.oschina.net/oscnet/up-1dc0d052149ec675f3e4fad632b82b48add.png)
![](https://oscimg.oschina.net/oscnet/up-de31bc2f9d9b8332c554b0954cc73d79593.png)
![](https://oscimg.oschina.net/oscnet/up-7f83b25159663686d67ed080eb16068c3b4.png)
##### 仪表盘设计器
![](https://oscimg.oschina.net/oscnet/up-9c9d41288c31398d76b390bdd400f13a582.png)
![](https://oscimg.oschina.net/oscnet/up-fad98d42b2cf92f92a903c9cff7579f18ec.png)
##### 报表设计器
![](https://oscimg.oschina.net/oscnet/up-64648de000851f15f6c7b9573d107ebb5f8.png)
![](https://oscimg.oschina.net/oscnet/up-fa52b44445db281c51d3f267dce7450d21b.gif)
![](https://oscimg.oschina.net/oscnet/up-68a19149d640f1646c8ed89ed4375e3326c.png)
![](https://oscimg.oschina.net/oscnet/up-f7e9cb2e3740f2d19ff63b40ec2dd554f96.png)
##### 表单设计器
![](https://oscimg.oschina.net/oscnet/up-5f8cb657615714b02190b355e59f60c5937.png)
![](https://oscimg.oschina.net/oscnet/up-d9659b2f324e33218476ec98c9b400e6508.png)
![](https://oscimg.oschina.net/oscnet/up-4868615395272d3206dbb960ade02dbc291.png)
##### 大屏设计器
![](https://oscimg.oschina.net/oscnet/up-402a6034124474bfef8dfc5b4b2bac1ce5c.png)
![](https://oscimg.oschina.net/oscnet/up-6f7ba2e2ebbeea0d203db8d69fd87644c9f.png)
![](https://oscimg.oschina.net/oscnet/up-ee8d34f318da466b8a6070a6e3111d12ce7.png)
![](https://oscimg.oschina.net/oscnet/up-6b81781b43086819049c4421206810667c5.png)
##### UNIAPP效果
![](https://oscimg.oschina.net/oscnet/up-aac943fbd26561879c57a41f7a406edf274.png)
![](https://oscimg.oschina.net/oscnet/up-9a44ba2e82b09c750629d12fafd7f60f553.png)
##### 零代码应用
![](https://oscimg.oschina.net/oscnet/up-4be29ae761b2615c8c54b3f668cd8432d9b.png)
![](https://oscimg.oschina.net/oscnet/up-787e76bc24b38ecc7ed19f338808d128255.png)
![](https://oscimg.oschina.net/oscnet/up-99d24a236c483362868523ad0d90f611487.png)
![](https://oscimg.oschina.net/oscnet/up-339a0f29d10449abc7724e3bcda802761c1.png)
![](https://oscimg.oschina.net/oscnet/up-b356670cdc14c609958c7619a537397c4b9.png)
##### 手机端
![](https://oscimg.oschina.net/oscnet/da543c5d0d57baab0cecaa4670c8b68c521.jpg)
![](https://oscimg.oschina.net/oscnet/fda4bd82cab9d682de1c1fbf2060bf14fa6.jpg)
##### PAD端
![](https://oscimg.oschina.net/oscnet/e90fef970a8c33790ab03ffd6c4c7cec225.jpg)
![](https://oscimg.oschina.net/oscnet/d78218803a9e856a0aa82b45efc49849a0c.jpg)
![](https://oscimg.oschina.net/oscnet/59c23b230f52384e588ee16309b44fa20de.jpg)
##### 图表示例
![](https://oscimg.oschina.net/oscnet/up-218bc6a1669496b241ebb23506440c0083e.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160834_Lo23.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160842_QK7B.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160849_GBm5.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160858_6RAM.png "在这里输入图片标题")
##### 在线接口文档
![输入图片说明](https://static.oschina.net/uploads/img/201908/27095258_M2Xq.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160957_hN3X.png "在这里输入图片标题")
## 捐赠
如果觉得还不错,请作者喝杯咖啡吧 ☺
![](https://static.oschina.net/uploads/img/201903/08155608_0EFX.png)
\ No newline at end of file
package org.jeecg.common.api.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("统一分页查询")
public class PageSearch<T> {
@ApiModelProperty(value = "当前页码")
private Integer pageNo = 1;
@ApiModelProperty(value = "每页记录数")
private Integer pageSize = 10;
@ApiModelProperty(value = "查询载体")
private T query;
}
......@@ -112,11 +112,10 @@ public class Swagger2Config implements WebMvcConfigurer {
.title("JeecgBoot 后台服务API接口文档")
// 版本号
.version("1.0")
// .termsOfServiceUrl("NO terms of service")
// 描述
.description("后台API接口")
// 作者
.contact(new Contact("北京敲敲云科技有限公司","www.jeccg.com","jeecgos@163.com"))
.contact(new Contact(" "," "," "))
.license("The Apache License, Version 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.build();
......
//package org.jeecg.config.mybatis;
//
//import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
//import net.sf.jsqlparser.expression.BinaryExpression;
//import net.sf.jsqlparser.expression.Expression;
//import net.sf.jsqlparser.expression.Parenthesis;
//import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
//import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
//import net.sf.jsqlparser.expression.operators.relational.*;
//import net.sf.jsqlparser.schema.Column;
//import net.sf.jsqlparser.schema.Table;
//import net.sf.jsqlparser.statement.select.*;
//
//import java.util.List;
//
///**
// * 复写租户条件
// */
//public class JeecgTenantParser extends TenantSqlParser {
//
// /**
// * @param expression
// * @param table
// * @return
// */
// protected Expression processTableAlias(Expression expression, Table table) {
// String tableAliasName;
// if (table.getAlias() == null) {
// tableAliasName = table.getName();
// } else {
// tableAliasName = table.getAlias().getName();
// }
//
// // in
// if (expression instanceof InExpression) {
// InExpression in = (InExpression) expression;
// if (in.getLeftExpression() instanceof Column) {
// setTableAliasNameForColumn((Column) in.getLeftExpression(), tableAliasName);
// }
//
// // 比较操作
// } else if (expression instanceof BinaryExpression) {
// BinaryExpression compare = (BinaryExpression) expression;
// if (compare.getLeftExpression() instanceof Column) {
// setTableAliasNameForColumn((Column) compare.getLeftExpression(), tableAliasName);
// } else if (compare.getRightExpression() instanceof Column) {
// setTableAliasNameForColumn((Column) compare.getRightExpression(), tableAliasName);
// }
//
// // between
// } else if (expression instanceof Between) {
// Between between = (Between) expression;
// if (between.getLeftExpression() instanceof Column) {
// setTableAliasNameForColumn((Column) between.getLeftExpression(), tableAliasName);
// }
// }
// return expression;
// }
//
// private void setTableAliasNameForColumn(Column column, String tableAliasName) {
// column.setColumnName(tableAliasName + "." + column.getColumnName());
// }
//
// /**
// * 默认是按 tenant_id=1 按等于条件追加
// *
// * @param currentExpression 现有的条件:比如你原来的sql查询条件
// * @param table
// * @return
// */
// @Override
// protected Expression builderExpression(Expression currentExpression, Table table) {
// final Expression tenantExpression = this.getTenantHandler().getTenantId(true);
// Expression appendExpression;
// if (!(tenantExpression instanceof SupportsOldOracleJoinSyntax)) {
// appendExpression = new EqualsTo();
// ((EqualsTo) appendExpression).setLeftExpression(this.getAliasColumn(table));
// ((EqualsTo) appendExpression).setRightExpression(tenantExpression);
// } else {
// appendExpression = processTableAlias(tenantExpression, table);
// }
// if (currentExpression == null) {
// return appendExpression;
// }
// if (currentExpression instanceof BinaryExpression) {
// BinaryExpression binaryExpression = (BinaryExpression) currentExpression;
// if (binaryExpression.getLeftExpression() instanceof FromItem) {
// processFromItem((FromItem) binaryExpression.getLeftExpression());
// }
// if (binaryExpression.getRightExpression() instanceof FromItem) {
// processFromItem((FromItem) binaryExpression.getRightExpression());
// }
// } else if (currentExpression instanceof InExpression) {
// InExpression inExp = (InExpression) currentExpression;
// ItemsList rightItems = inExp.getRightItemsList();
// if (rightItems instanceof SubSelect) {
// processSelectBody(((SubSelect) rightItems).getSelectBody());
// }
// }
// if (currentExpression instanceof OrExpression) {
// return new AndExpression(new Parenthesis(currentExpression), appendExpression);
// } else {
// return new AndExpression(currentExpression, appendExpression);
// }
// }
//
// @Override
// protected void processPlainSelect(PlainSelect plainSelect, boolean addColumn) {
// FromItem fromItem = plainSelect.getFromItem();
// if (fromItem instanceof Table) {
// Table fromTable = (Table) fromItem;
// if (!this.getTenantHandler().doTableFilter(fromTable.getName())) {
// plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable));
// if (addColumn) {
// plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(this.getTenantHandler().getTenantIdColumn())));
// }
// }
// } else {
// processFromItem(fromItem);
// }
// List<Join> joins = plainSelect.getJoins();
// if (joins != null && joins.size() > 0) {
// joins.forEach(j -> {
// processJoin(j);
// processFromItem(j.getRightItem());
// });
// }
// }
//
//}
//package org.jeecg.config.mybatis;
//
//import lombok.extern.slf4j.Slf4j;
//
///**
// * 多租户 tenant_id存储器
// * @author: jeecg-boot
// */
//@Slf4j
//public class TenantContext {
// private static ThreadLocal<String> currentTenant = new ThreadLocal<>();
//
// public static void setTenant(String tenant) {
// log.debug(" setting tenant to " + tenant);
// currentTenant.set(tenant);
// }
//
// public static String getTenant() {
// return currentTenant.get();
// }
//
// public static void clear(){
// currentTenant.remove();
// }
//}
......@@ -65,89 +65,89 @@ public class ShiroConfig {
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//支持yml方式,配置拦截排除
if(jeecgBaseConfig!=null && jeecgBaseConfig.getShiro()!=null){
String shiroExcludeUrls = jeecgBaseConfig.getShiro().getExcludeUrls();
if(oConvertUtils.isNotEmpty(shiroExcludeUrls)){
String[] permissionUrl = shiroExcludeUrls.split(",");
for(String url : permissionUrl){
filterChainDefinitionMap.put(url,"anon");
}
}
}
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录
filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录
filterChainDefinitionMap.put("/sys/getEncryptedString", "anon"); //获取加密串
filterChainDefinitionMap.put("/sys/sms", "anon");//短信验证码
filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录
filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在
filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册
filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号
filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码
filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token
filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览
filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件
filterChainDefinitionMap.put("/sys/getLoginQrcode/**", "anon"); //登录二维码
filterChainDefinitionMap.put("/sys/getQrcodeToken/**", "anon"); //监听扫码
filterChainDefinitionMap.put("/sys/checkAuth", "anon"); //授权接口排除
filterChainDefinitionMap.put("/", "anon");
filterChainDefinitionMap.put("/doc.html", "anon");
filterChainDefinitionMap.put("/**/*.js", "anon");
filterChainDefinitionMap.put("/**/*.css", "anon");
filterChainDefinitionMap.put("/**/*.html", "anon");
filterChainDefinitionMap.put("/**/*.svg", "anon");
filterChainDefinitionMap.put("/**/*.pdf", "anon");
filterChainDefinitionMap.put("/**/*.jpg", "anon");
filterChainDefinitionMap.put("/**/*.png", "anon");
filterChainDefinitionMap.put("/**/*.gif", "anon");
filterChainDefinitionMap.put("/**/*.ico", "anon");
filterChainDefinitionMap.put("/**/*.ttf", "anon");
filterChainDefinitionMap.put("/**/*.woff", "anon");
filterChainDefinitionMap.put("/**/*.woff2", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger**/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/v2/**", "anon");
filterChainDefinitionMap.put("/sys/annountCement/show/**", "anon");
//积木报表排除
filterChainDefinitionMap.put("/jmreport/**", "anon");
filterChainDefinitionMap.put("/**/*.js.map", "anon");
filterChainDefinitionMap.put("/**/*.css.map", "anon");
//大屏模板例子
filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
// if(jeecgBaseConfig!=null && jeecgBaseConfig.getShiro()!=null){
// String shiroExcludeUrls = jeecgBaseConfig.getShiro().getExcludeUrls();
// if(oConvertUtils.isNotEmpty(shiroExcludeUrls)){
// String[] permissionUrl = shiroExcludeUrls.split(",");
// for(String url : permissionUrl){
// filterChainDefinitionMap.put(url,"anon");
// }
// }
// }
// // 配置不会被拦截的链接 顺序判断
// filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录
// filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
// filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
// filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
// filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
// filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
// filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录
// filterChainDefinitionMap.put("/sys/getEncryptedString", "anon"); //获取加密串
// filterChainDefinitionMap.put("/sys/sms", "anon");//短信验证码
// filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录
// filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在
// filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册
// filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号
// filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码
// filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
// filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token
// filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览
// filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件
//
// filterChainDefinitionMap.put("/sys/getLoginQrcode/**", "anon"); //登录二维码
// filterChainDefinitionMap.put("/sys/getQrcodeToken/**", "anon"); //监听扫码
// filterChainDefinitionMap.put("/sys/checkAuth", "anon"); //授权接口排除
//
//
// filterChainDefinitionMap.put("/", "anon");
// filterChainDefinitionMap.put("/doc.html", "anon");
// filterChainDefinitionMap.put("/**/*.js", "anon");
// filterChainDefinitionMap.put("/**/*.css", "anon");
// filterChainDefinitionMap.put("/**/*.html", "anon");
// filterChainDefinitionMap.put("/**/*.svg", "anon");
// filterChainDefinitionMap.put("/**/*.pdf", "anon");
// filterChainDefinitionMap.put("/**/*.jpg", "anon");
// filterChainDefinitionMap.put("/**/*.png", "anon");
// filterChainDefinitionMap.put("/**/*.gif", "anon");
// filterChainDefinitionMap.put("/**/*.ico", "anon");
// filterChainDefinitionMap.put("/**/*.ttf", "anon");
// filterChainDefinitionMap.put("/**/*.woff", "anon");
// filterChainDefinitionMap.put("/**/*.woff2", "anon");
//
// filterChainDefinitionMap.put("/druid/**", "anon");
// filterChainDefinitionMap.put("/swagger-ui.html", "anon");
// filterChainDefinitionMap.put("/swagger**/**", "anon");
// filterChainDefinitionMap.put("/webjars/**", "anon");
// filterChainDefinitionMap.put("/v2/**", "anon");
//
// filterChainDefinitionMap.put("/sys/annountCement/show/**", "anon");
//
// //积木报表排除
// filterChainDefinitionMap.put("/jmreport/**", "anon");
// filterChainDefinitionMap.put("/**/*.js.map", "anon");
// filterChainDefinitionMap.put("/**/*.css.map", "anon");
//
// //大屏模板例子
// filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
// filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
// filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
//filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试
//filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面
//filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试
//websocket排除
filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告
filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块
filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
// filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告
// filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块
// filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
//性能监控——安全隐患泄露TOEKN(durid连接池也有)
//filterChainDefinitionMap.put("/actuator/**", "anon");
//测试模块排除
filterChainDefinitionMap.put("/test/seata/**", "anon");
// filterChainDefinitionMap.put("/test/seata/**", "anon");
// update-begin--author:liusq Date:20230522 for:[issues/4829]访问不存在的url时会提示Token失效,请重新登录呢
//错误路径排除
filterChainDefinitionMap.put("/error", "anon");
filterChainDefinitionMap.put("/**", "anon");
// update-end--author:liusq Date:20230522 for:[issues/4829]访问不存在的url时会提示Token失效,请重新登录呢
// 添加自己的过滤器并且取名为jwt
......@@ -157,7 +157,7 @@ public class ShiroConfig {
filterMap.put("jwt", new JwtFilter(cloudServer==null));
shiroFilterFactoryBean.setFilters(filterMap);
// <!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边
filterChainDefinitionMap.put("/**", "jwt");
// filterChainDefinitionMap.put("/**", "jwt");
// 未授权界面返回JSON
shiroFilterFactoryBean.setUnauthorizedUrl("/sys/common/403");
......
......@@ -4,8 +4,11 @@ import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.util.ObjectUtil;
import org.jeecg.common.api.dto.PageSearch;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.subwayNetwork.dto.LightRailQueryDTO;
import org.jeecg.modules.subwayNetwork.entity.LightRail;
import org.jeecg.modules.subwayNetwork.service.ILightRailService;
......@@ -15,6 +18,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.modules.subwayNetwork.vo.LightRailQueryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
......@@ -40,52 +44,28 @@ public class LightRailController extends JeecgController<LightRail, ILightRailSe
/**
* 分页列表查询
*
* @param lightRail
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "线路车站-轻轨线路-分页列表查询")
@AutoLog(value = "线路车站-轻轨线路-分页列表查询")
@ApiOperation(value = "线路车站-轻轨线路-分页列表查询", notes = "线路车站-轻轨线路-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<LightRail>> queryPageList(LightRail lightRail,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<LightRail> queryWrapper = QueryGenerator.initQueryWrapper(lightRail, req.getParameterMap());
Page<LightRail> page = new Page<LightRail>(pageNo, pageSize);
IPage<LightRail> pageList = lightRailService.page(page, queryWrapper);
@PostMapping(value = "/list")
public Result<IPage<LightRailQueryVO>> queryPageList(@RequestBody PageSearch<LightRailQueryDTO> dto) {
IPage<LightRailQueryVO> pageList = lightRailService.queryPageList(dto);
return Result.OK(pageList);
}
/**
* 添加
*
* @param lightRail
* @return
*/
@AutoLog(value = "线路车站-轻轨线路-添加")
@ApiOperation(value = "线路车站-轻轨线路-添加", notes = "线路车站-轻轨线路-添加")
// @RequiresPermissions("subwayNetwork:t_sn_light_rail:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody LightRail lightRail) {
lightRailService.save(lightRail);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param lightRail
* @return
*/
@AutoLog(value = "线路车站-轻轨线路-编辑")
@ApiOperation(value = "线路车站-轻轨线路-编辑", notes = "线路车站-轻轨线路-编辑")
// @RequiresPermissions("subwayNetwork:t_sn_light_rail:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody LightRail lightRail) {
lightRailService.updateById(lightRail);
if (ObjectUtil.isEmpty(lightRail.getId())) {
lightRailService.save(lightRail);
} else {
lightRailService.updateById(lightRail);
}
return Result.OK("编辑成功!");
}
......@@ -97,8 +77,7 @@ public class LightRailController extends JeecgController<LightRail, ILightRailSe
*/
@AutoLog(value = "线路车站-轻轨线路-通过id删除")
@ApiOperation(value = "线路车站-轻轨线路-通过id删除", notes = "线路车站-轻轨线路-通过id删除")
// @RequiresPermissions("subwayNetwork:t_sn_light_rail:delete")
@DeleteMapping(value = "/delete")
@GetMapping(value = "/delete")
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
lightRailService.removeById(id);
return Result.OK("删除成功!");
......@@ -112,8 +91,7 @@ public class LightRailController extends JeecgController<LightRail, ILightRailSe
*/
@AutoLog(value = "线路车站-轻轨线路-批量删除")
@ApiOperation(value = "线路车站-轻轨线路-批量删除", notes = "线路车站-轻轨线路-批量删除")
// @RequiresPermissions("subwayNetwork:t_sn_light_rail:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
@GetMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.lightRailService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
......@@ -125,7 +103,7 @@ public class LightRailController extends JeecgController<LightRail, ILightRailSe
* @param id
* @return
*/
//@AutoLog(value = "线路车站-轻轨线路-通过id查询")
@AutoLog(value = "线路车站-轻轨线路-通过id查询")
@ApiOperation(value = "线路车站-轻轨线路-通过id查询", notes = "线路车站-轻轨线路-通过id查询")
@GetMapping(value = "/queryById")
public Result<LightRail> queryById(@RequestParam(name = "id", required = true) String id) {
......@@ -136,29 +114,4 @@ public class LightRailController extends JeecgController<LightRail, ILightRailSe
return Result.OK(lightRail);
}
/**
* 导出excel
*
* @param request
* @param lightRail
*/
// @RequiresPermissions("subwayNetwork:t_sn_light_rail:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, LightRail lightRail) {
return super.exportXls(request, lightRail, LightRail.class, "线路车站-轻轨线路");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
// @RequiresPermissions("subwayNetwork:t_sn_light_rail:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, LightRail.class);
}
}
package org.jeecg.modules.subwayNetwork.controller;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.subwayNetwork.entity.SectionStationMap;
import org.jeecg.modules.subwayNetwork.service.ISectionStationMapService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
* @Description: 线路车站-区间站点映射
* @Author: jeecg-boot
* @Date: 2023-06-15
* @Version: V1.0
*/
@Api(tags="线路车站-区间站点映射")
@RestController
@RequestMapping("/subwayNetwork/sectionStationMap")
@Slf4j
public class SectionStationMapController extends JeecgController<SectionStationMap, ISectionStationMapService> {
@Autowired
private ISectionStationMapService sectionStationMapService;
/**
* 分页列表查询
*
* @param sectionStationMap
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "线路车站-区间站点映射-分页列表查询")
@ApiOperation(value="线路车站-区间站点映射-分页列表查询", notes="线路车站-区间站点映射-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<SectionStationMap>> queryPageList(SectionStationMap sectionStationMap,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<SectionStationMap> queryWrapper = QueryGenerator.initQueryWrapper(sectionStationMap, req.getParameterMap());
Page<SectionStationMap> page = new Page<SectionStationMap>(pageNo, pageSize);
IPage<SectionStationMap> pageList = sectionStationMapService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param sectionStationMap
* @return
*/
@AutoLog(value = "线路车站-区间站点映射-添加")
@ApiOperation(value="线路车站-区间站点映射-添加", notes="线路车站-区间站点映射-添加")
@RequiresPermissions("subwayNetwork:t_sn_section_station_map:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody SectionStationMap sectionStationMap) {
sectionStationMapService.save(sectionStationMap);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param sectionStationMap
* @return
*/
@AutoLog(value = "线路车站-区间站点映射-编辑")
@ApiOperation(value="线路车站-区间站点映射-编辑", notes="线路车站-区间站点映射-编辑")
@RequiresPermissions("subwayNetwork:t_sn_section_station_map:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody SectionStationMap sectionStationMap) {
sectionStationMapService.updateById(sectionStationMap);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "线路车站-区间站点映射-通过id删除")
@ApiOperation(value="线路车站-区间站点映射-通过id删除", notes="线路车站-区间站点映射-通过id删除")
@RequiresPermissions("subwayNetwork:t_sn_section_station_map:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
sectionStationMapService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "线路车站-区间站点映射-批量删除")
@ApiOperation(value="线路车站-区间站点映射-批量删除", notes="线路车站-区间站点映射-批量删除")
@RequiresPermissions("subwayNetwork:t_sn_section_station_map:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.sectionStationMapService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "线路车站-区间站点映射-通过id查询")
@ApiOperation(value="线路车站-区间站点映射-通过id查询", notes="线路车站-区间站点映射-通过id查询")
@GetMapping(value = "/queryById")
public Result<SectionStationMap> queryById(@RequestParam(name="id",required=true) String id) {
SectionStationMap sectionStationMap = sectionStationMapService.getById(id);
if(sectionStationMap==null) {
return Result.error("未找到对应数据");
}
return Result.OK(sectionStationMap);
}
/**
* 导出excel
*
* @param request
* @param sectionStationMap
*/
@RequiresPermissions("subwayNetwork:t_sn_section_station_map:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, SectionStationMap sectionStationMap) {
return super.exportXls(request, sectionStationMap, SectionStationMap.class, "线路车站-区间站点映射");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequiresPermissions("subwayNetwork:t_sn_section_station_map:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, SectionStationMap.class);
}
}
......@@ -6,6 +6,7 @@ import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.subwayNetwork.dto.SubwaySectionEditDTO;
import org.jeecg.modules.subwayNetwork.entity.SubwaySection;
import org.jeecg.modules.subwayNetwork.service.ISubwaySectionService;
......@@ -37,16 +38,7 @@ public class SubwaySectionController extends JeecgController<SubwaySection, ISub
@Autowired
private ISubwaySectionService subwaySectionService;
/**
* 分页列表查询
*
* @param subwaySection
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "线路车站-地铁区间-分页列表查询")
@AutoLog(value = "线路车站-地铁区间-分页列表查询")
@ApiOperation(value = "线路车站-地铁区间-分页列表查询", notes = "线路车站-地铁区间-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<SubwaySection>> queryPageList(SubwaySection subwaySection,
......@@ -59,72 +51,31 @@ public class SubwaySectionController extends JeecgController<SubwaySection, ISub
return Result.OK(pageList);
}
/**
* 添加
*
* @param subwaySection
* @return
*/
@AutoLog(value = "线路车站-地铁区间-添加")
@ApiOperation(value = "线路车站-地铁区间-添加", notes = "线路车站-地铁区间-添加")
@RequiresPermissions("subwayNetwork:t_sn_subway_section:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody SubwaySection subwaySection) {
subwaySectionService.save(subwaySection);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param subwaySection
* @return
*/
@AutoLog(value = "线路车站-地铁区间-编辑")
@ApiOperation(value = "线路车站-地铁区间-编辑", notes = "线路车站-地铁区间-编辑")
@RequiresPermissions("subwayNetwork:t_sn_subway_section:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
public Result<String> edit(@RequestBody SubwaySection subwaySection) {
subwaySectionService.updateById(subwaySection);
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody SubwaySectionEditDTO dto) {
subwaySectionService.edit(dto);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "线路车站-地铁区间-通过id删除")
@ApiOperation(value = "线路车站-地铁区间-通过id删除", notes = "线路车站-地铁区间-通过id删除")
@RequiresPermissions("subwayNetwork:t_sn_subway_section:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
subwaySectionService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "线路车站-地铁区间-批量删除")
@ApiOperation(value = "线路车站-地铁区间-批量删除", notes = "线路车站-地铁区间-批量删除")
@RequiresPermissions("subwayNetwork:t_sn_subway_section:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.subwaySectionService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "线路车站-地铁区间-通过id查询")
@ApiOperation(value = "线路车站-地铁区间-通过id查询", notes = "线路车站-地铁区间-通过id查询")
@GetMapping(value = "/queryById")
......@@ -136,29 +87,4 @@ public class SubwaySectionController extends JeecgController<SubwaySection, ISub
return Result.OK(subwaySection);
}
/**
* 导出excel
*
* @param request
* @param subwaySection
*/
@RequiresPermissions("subwayNetwork:t_sn_subway_section:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, SubwaySection subwaySection) {
return super.exportXls(request, subwaySection, SubwaySection.class, "线路车站-地铁区间");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequiresPermissions("subwayNetwork:t_sn_subway_section:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, SubwaySection.class);
}
}
package org.jeecg.modules.subwayNetwork.controller;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.subwayNetwork.entity.TrainStation;
import org.jeecg.modules.subwayNetwork.service.ITrainStationService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.PageSearch;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.modules.subwayNetwork.dto.TrainStationQueryDTO;
import org.jeecg.modules.subwayNetwork.entity.TrainStation;
import org.jeecg.modules.subwayNetwork.service.ITrainStationService;
import org.jeecg.modules.subwayNetwork.vo.TrainStationVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
import java.util.Arrays;
/**
* @Description: 线路车站-地铁站
* @Author: jeecg-boot
* @Date: 2023-06-14
* @Date: 2023-06-14
* @Version: V1.0
*/
@Api(tags="线路车站-地铁站")
@Api(tags = "线路车站-地铁站")
@RestController
@RequestMapping("/subwayNetwork/trainStation")
@Slf4j
public class TrainStationController extends JeecgController<TrainStation, ITrainStationService> {
@Autowired
private ITrainStationService trainStationService;
/**
* 分页列表查询
*
* @param trainStation
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "线路车站-地铁站-分页列表查询")
@ApiOperation(value="线路车站-地铁站-分页列表查询", notes="线路车站-地铁站-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<TrainStation>> queryPageList(TrainStation trainStation,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<TrainStation> queryWrapper = QueryGenerator.initQueryWrapper(trainStation, req.getParameterMap());
Page<TrainStation> page = new Page<TrainStation>(pageNo, pageSize);
IPage<TrainStation> pageList = trainStationService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param trainStation
* @return
*/
@AutoLog(value = "线路车站-地铁站-添加")
@ApiOperation(value="线路车站-地铁站-添加", notes="线路车站-地铁站-添加")
// @RequiresPermissions("subwayNetwork:t_sn_train_station:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody TrainStation trainStation) {
trainStationService.save(trainStation);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param trainStation
* @return
*/
@AutoLog(value = "线路车站-地铁站-编辑")
@ApiOperation(value="线路车站-地铁站-编辑", notes="线路车站-地铁站-编辑")
// @RequiresPermissions("subwayNetwork:t_sn_train_station:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody TrainStation trainStation) {
trainStationService.updateById(trainStation);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "线路车站-地铁站-通过id删除")
@ApiOperation(value="线路车站-地铁站-通过id删除", notes="线路车站-地铁站-通过id删除")
// @RequiresPermissions("subwayNetwork:t_sn_train_station:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
trainStationService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "线路车站-地铁站-批量删除")
@ApiOperation(value="线路车站-地铁站-批量删除", notes="线路车站-地铁站-批量删除")
// @RequiresPermissions("subwayNetwork:t_sn_train_station:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.trainStationService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "线路车站-地铁站-通过id查询")
@ApiOperation(value="线路车站-地铁站-通过id查询", notes="线路车站-地铁站-通过id查询")
@GetMapping(value = "/queryById")
public Result<TrainStation> queryById(@RequestParam(name="id",required=true) String id) {
TrainStation trainStation = trainStationService.getById(id);
if(trainStation==null) {
return Result.error("未找到对应数据");
}
return Result.OK(trainStation);
}
@Autowired
private ITrainStationService trainStationService;
/**
* 导出excel
*
* @param request
* @param trainStation
*/
// @RequiresPermissions("subwayNetwork:t_sn_train_station:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, TrainStation trainStation) {
return super.exportXls(request, trainStation, TrainStation.class, "线路车站-地铁站");
@AutoLog(value = "线路车站-地铁站-分页列表查询")
@ApiOperation(value = "线路车站-地铁站-分页列表查询", notes = "线路车站-地铁站-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<TrainStationVO>> queryPageList(@RequestBody PageSearch<TrainStationQueryDTO> dto) {
IPage<TrainStationVO> pageList = trainStationService.queryPageList(dto);
return Result.OK(pageList);
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
// @RequiresPermissions("subwayNetwork:t_sn_train_station:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, TrainStation.class);
@AutoLog(value = "线路车站-地铁站-添加")
@ApiOperation(value = "线路车站-地铁站-添加", notes = "线路车站-地铁站-添加")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody TrainStation trainStation) {
trainStationService.save(trainStation);
return Result.OK("添加成功!");
}
@AutoLog(value = "线路车站-地铁站-编辑")
@ApiOperation(value = "线路车站-地铁站-编辑", notes = "线路车站-地铁站-编辑")
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody TrainStation trainStation) {
trainStationService.updateById(trainStation);
return Result.OK("编辑成功!");
}
@AutoLog(value = "线路车站-地铁站-通过id删除")
@ApiOperation(value = "线路车站-地铁站-通过id删除", notes = "线路车站-地铁站-通过id删除")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
trainStationService.removeById(id);
return Result.OK("删除成功!");
}
@AutoLog(value = "线路车站-地铁站-批量删除")
@ApiOperation(value = "线路车站-地铁站-批量删除", notes = "线路车站-地铁站-批量删除")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.trainStationService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
}
package org.jeecg.modules.subwayNetwork.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "线路DTO")
public class LightRailQueryDTO {
@ApiModelProperty(value = "线路name")
private String railLineName;
@ApiModelProperty(value = "状态")
private String status;
}
package org.jeecg.modules.subwayNetwork.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.jeecgframework.poi.excel.annotation.Excel;
@Data
@ApiModel(value = "区间DTO")
public class SubwaySectionDTO {
@ApiModelProperty(value = "线路id")
private java.lang.String railId;
}
package org.jeecg.modules.subwayNetwork.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel(value = "SubwaySectionEditDTO编辑")
public class SubwaySectionEditDTO {
}
package org.jeecg.modules.subwayNetwork.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ApiModel(value = "地铁站DTO")
public class TrainStationQueryDTO {
@ApiModelProperty(value = "车站名")
private String stationName;
}
......@@ -4,10 +4,8 @@ import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
......@@ -21,47 +19,45 @@ import lombok.experimental.Accessors;
/**
* @Description: 线路车站-轻轨线路
* @Author: jeecg-boot
* @Date: 2023-06-14
* @Date: 2023-06-14
* @Version: V1.0
*/
@Data
@TableName("t_sn_light_rail")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="t_sn_light_rail对象", description="线路车站-轻轨线路")
@ApiModel(value = "t_sn_light_rail对象", description = "线路车站-轻轨线路")
public class LightRail implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.ASSIGN_ID)
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private java.lang.String id;
/**创建人*/
@ApiModelProperty(value = "创建人")
private java.lang.String createBy;
/**创建日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建日期")
private java.util.Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private java.lang.String updateBy;
/**更新日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private String updateBy;
@ApiModelProperty(value = "更新日期")
private java.util.Date updateTime;
/**线路名称*/
@Excel(name = "线路名称", width = 15)
private Date updateTime;
@ApiModelProperty(value = "线路名称")
private java.lang.String railLineName;
/**线路code*/
@Excel(name = "线路code", width = 15)
private String railLineName;
@ApiModelProperty(value = "线路code")
private java.lang.String railLineCode;
/**状态*/
@Excel(name = "状态", width = 15)
private String railLineCode;
@ApiModelProperty(value = "状态")
private java.lang.String status;
private Integer status;
}
......@@ -53,71 +53,52 @@ public class TrainStation implements Serializable {
*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* 更新日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新日期")
private Date updateTime;
/**
* 轻轨线路ID
*/
@Excel(name = "轻轨线路ID", width = 15)
@ApiModelProperty(value = "轻轨线路ID")
private String lightRailId;
/**
* 车站名
*/
@Excel(name = "车站名", width = 15)
@ApiModelProperty(value = "车站名")
private String stationName;
/**
* 车站编码
*/
@Excel(name = "车站编码", width = 15)
@ApiModelProperty(value = "车站编码")
private String stationCode;
/**
* 线别
*/
@Excel(name = "线别", width = 15)
@ApiModelProperty(value = "线别")
private String lineAlias;
/**
* 起始里程前缀
*/
@Excel(name = "起始里程前缀", width = 15)
@ApiModelProperty(value = "起始里程前缀")
private String startingMileagePrefix;
/**
* 起始里程
*/
@Excel(name = "起始里程", width = 15)
@ApiModelProperty(value = "起始里程")
private BigDecimal startingMileage;
/**
* 中心里程前缀
*/
@Excel(name = "中心里程前缀", width = 15)
@ApiModelProperty(value = "中心里程前缀")
private String centerMileagePrefix;
/**
* 中心里程
*/
@Excel(name = "中心里程", width = 15)
@ApiModelProperty(value = "中心里程")
private BigDecimal centerMileage;
/**
* 结束里程前缀
*/
@Excel(name = "结束里程前缀", width = 15)
@ApiModelProperty(value = "结束里程前缀")
private String endMileagePrefix;
/**
* 结束里程
*/
@Excel(name = "结束里程", width = 15)
@ApiModelProperty(value = "结束里程")
private BigDecimal endMileage;
@ApiModelProperty(value = "序号")
private Integer seq;
}
package org.jeecg.modules.subwayNetwork.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.jeecg.modules.subwayNetwork.dto.LightRailQueryDTO;
import org.jeecg.modules.subwayNetwork.entity.LightRail;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.subwayNetwork.vo.LightRailQueryVO;
/**
* @Description: 线路车站-轻轨线路
* @Author: jeecg-boot
* @Date: 2023-06-14
* @Date: 2023-06-14
* @Version: V1.0
*/
public interface LightRailMapper extends BaseMapper<LightRail> {
IPage<LightRailQueryVO> queryPageList(IPage<LightRailQueryVO> page, LightRailQueryDTO query);
}
package org.jeecg.modules.subwayNetwork.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.jeecg.modules.subwayNetwork.dto.TrainStationQueryDTO;
import org.jeecg.modules.subwayNetwork.entity.TrainStation;
import org.jeecg.modules.subwayNetwork.vo.LightRailQueryVO;
import org.jeecg.modules.subwayNetwork.vo.TrainStationVO;
/**
* @Description: 线路车站-地铁站
......@@ -11,4 +15,5 @@ import org.jeecg.modules.subwayNetwork.entity.TrainStation;
*/
public interface TrainStationMapper extends BaseMapper<TrainStation> {
IPage<TrainStationVO> queryPageList(IPage<LightRailQueryVO> page, TrainStationQueryDTO query);
}
......@@ -2,4 +2,32 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.subwayNetwork.mapper.LightRailMapper">
<select id="queryPageList" resultType="org.jeecg.modules.subwayNetwork.vo.LightRailQueryVO">
SELECT
t1.create_by,
t1.create_time,
t1.id,
t1.rail_line_code,
t1.rail_line_name,
t1.status,
t1.update_by,
t1.update_time,
count(t2.id) subwaySectionNum,
count(t3.id) trainStationNum,
ifnull(sum(t3.end_mileage),0) lineMileage
FROM
t_sn_light_rail t1
LEFT JOIN t_sn_subway_section t2 ON t1.id = t2.rail_id
LEFT JOIN t_sn_train_station t3 ON t1.id = t3.light_rail_id
<where>
<if test="query.railLineName != null and query.railLineName != ''">
AND t1.rail_line_name like concat('%',#{query.railLineName},'%')
</if>
<if test="query.status != null and query.status != ''">
AND t1.status = #{query.status}
</if>
</where>
GROUP BY t1.id
</select>
</mapper>
\ No newline at end of file
......@@ -2,4 +2,44 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.subwayNetwork.mapper.TrainStationMapper">
<select id="queryPageList" resultType="org.jeecg.modules.subwayNetwork.vo.TrainStationVO">
SELECT
t1.center_mileage,
t1.center_mileage_prefix,
t1.create_by,
t1.create_time,
t1.end_mileage,
t1.end_mileage_prefix,
t1.id,
t1.light_rail_id,
t1.line_alias,
t1.starting_mileage,
t1.starting_mileage_prefix,
t1.station_code,
t1.station_name,
t1.update_by,
t1.update_time,
t1.center_mileage,
t1.center_mileage_prefix,
t1.create_by,
t1.create_time,
t1.end_mileage,
t1.end_mileage_prefix,
t1.id,
t1.light_rail_id,
t1.line_alias,
t1.starting_mileage,
t1.starting_mileage_prefix,
t1.station_code,
t1.station_name,
t1.update_by,
t1.update_time
FROM
t_sn_train_station t1
<where>
<if test="query.stationName !=null and query.stationName!=''">
AND t1.station_name like concat('%',#{query.stationName},'%')
</if>
</where>
</select>
</mapper>
\ No newline at end of file
package org.jeecg.modules.subwayNetwork.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.jeecg.common.api.dto.PageSearch;
import org.jeecg.modules.subwayNetwork.dto.LightRailQueryDTO;
import org.jeecg.modules.subwayNetwork.entity.LightRail;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.subwayNetwork.vo.LightRailQueryVO;
/**
* @Description: 线路车站-轻轨线路
* @Author: jeecg-boot
* @Date: 2023-06-14
* @Date: 2023-06-14
* @Version: V1.0
*/
public interface ILightRailService extends IService<LightRail> {
/**
* 分页查询
*
* @param dto
* @return
*/
IPage<LightRailQueryVO> queryPageList(PageSearch<LightRailQueryDTO> dto);
}
package org.jeecg.modules.subwayNetwork.service;
import org.jeecg.modules.subwayNetwork.dto.SubwaySectionEditDTO;
import org.jeecg.modules.subwayNetwork.entity.SubwaySection;
import com.baomidou.mybatisplus.extension.service.IService;
......@@ -11,4 +12,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface ISubwaySectionService extends IService<SubwaySection> {
void edit(SubwaySectionEditDTO dto);
}
package org.jeecg.modules.subwayNetwork.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.dto.PageSearch;
import org.jeecg.modules.subwayNetwork.dto.TrainStationQueryDTO;
import org.jeecg.modules.subwayNetwork.entity.TrainStation;
import org.jeecg.modules.subwayNetwork.vo.TrainStationVO;
/**
* @Description: 线路车站-地铁站
* @Author: jeecg-boot
* @Date: 2023-06-14
* @Date: 2023-06-14
* @Version: V1.0
*/
public interface ITrainStationService extends IService<TrainStation> {
IPage<TrainStationVO> queryPageList(PageSearch<TrainStationQueryDTO> dto);
}
package org.jeecg.modules.subwayNetwork.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.api.dto.PageSearch;
import org.jeecg.modules.subwayNetwork.dto.LightRailQueryDTO;
import org.jeecg.modules.subwayNetwork.entity.LightRail;
import org.jeecg.modules.subwayNetwork.entity.SectionStationMap;
import org.jeecg.modules.subwayNetwork.mapper.LightRailMapper;
import org.jeecg.modules.subwayNetwork.service.ILightRailService;
import org.jeecg.modules.subwayNetwork.vo.LightRailQueryVO;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: 线路车站-轻轨线路
* @Author: jeecg-boot
* @Date: 2023-06-14
* @Date: 2023-06-14
* @Version: V1.0
*/
@Service
public class LightRailServiceImpl extends ServiceImpl<LightRailMapper, LightRail> implements ILightRailService {
@Override
public IPage<LightRailQueryVO> queryPageList(PageSearch<LightRailQueryDTO> dto) {
IPage<LightRailQueryVO> page = new Page<>(dto.getPageNo(), dto.getPageSize());
page = this.baseMapper.queryPageList(page, dto.getQuery());
return page;
}
}
package org.jeecg.modules.subwayNetwork.service.impl;
import org.jeecg.modules.subwayNetwork.dto.SubwaySectionEditDTO;
import org.jeecg.modules.subwayNetwork.entity.SubwaySection;
import org.jeecg.modules.subwayNetwork.mapper.SubwaySectionMapper;
import org.jeecg.modules.subwayNetwork.service.ISubwaySectionService;
......@@ -16,4 +17,9 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@Service
public class SubwaySectionServiceImpl extends ServiceImpl<SubwaySectionMapper, SubwaySection> implements ISubwaySectionService {
@Override
public void edit(SubwaySectionEditDTO dto) {
}
}
package org.jeecg.modules.subwayNetwork.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.common.api.dto.PageSearch;
import org.jeecg.modules.subwayNetwork.dto.TrainStationQueryDTO;
import org.jeecg.modules.subwayNetwork.mapper.TrainStationMapper;
import org.jeecg.modules.subwayNetwork.service.ITrainStationService;
import org.jeecg.modules.subwayNetwork.entity.TrainStation;
import org.jeecg.modules.subwayNetwork.vo.LightRailQueryVO;
import org.jeecg.modules.subwayNetwork.vo.TrainStationVO;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
......@@ -15,4 +21,9 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@Service
public class TrainStationServiceImpl extends ServiceImpl<TrainStationMapper, TrainStation> implements ITrainStationService {
@Override
public IPage<TrainStationVO> queryPageList(PageSearch<TrainStationQueryDTO> dto) {
IPage<LightRailQueryVO> page = new Page<>(dto.getPageNo(), dto.getPageSize());
return this.baseMapper.queryPageList(page,dto.getQuery());
}
}
package org.jeecg.modules.subwayNetwork.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ApiModel(value = "线路VO")
public class LightRailQueryVO {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
private String id;
@ApiModelProperty(value = "创建人")
private String createBy;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建日期")
private Date createTime;
@ApiModelProperty(value = "更新人")
private String updateBy;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新日期")
private Date updateTime;
@ApiModelProperty(value = "线路名称")
private java.lang.String railLineName;
@ApiModelProperty(value = "线路code")
private java.lang.String railLineCode;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "区间数量")
private Integer subwaySectionNum;
@ApiModelProperty(value = "车站数量")
private Integer trainStationNum;
@ApiModelProperty(value = "线路里程")
private BigDecimal lineMileage;
}
package org.jeecg.modules.subwayNetwork.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel(value = "区间VO")
public class SubwaySectionVO {
}
package org.jeecg.modules.subwayNetwork.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ApiModel(value = "地铁站VO")
public class TrainStationVO {
@ApiModelProperty(value = "主键")
private String id;
@ApiModelProperty(value = "创建人")
private String createBy;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建日期")
private Date createTime;
@ApiModelProperty(value = "更新人")
private String updateBy;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新日期")
private Date updateTime;
@ApiModelProperty(value = "轻轨线路ID")
private String lightRailId;
@ApiModelProperty(value = "车站名")
private String stationName;
@ApiModelProperty(value = "车站编码")
private String stationCode;
@ApiModelProperty(value = "线别")
private String lineAlias;
@ApiModelProperty(value = "起始里程前缀")
private String startingMileagePrefix;
@ApiModelProperty(value = "起始里程")
private BigDecimal startingMileage;
@ApiModelProperty(value = "中心里程前缀")
private String centerMileagePrefix;
@ApiModelProperty(value = "中心里程")
private BigDecimal centerMileage;
@ApiModelProperty(value = "结束里程前缀")
private String endMileagePrefix;
@ApiModelProperty(value = "结束里程")
private BigDecimal endMileage;
}
......@@ -44,691 +44,704 @@ import java.util.*;
*/
@RestController
@RequestMapping("/sys")
@Api(tags="用户登录")
@Api(tags = "用户登录")
@Slf4j
public class LoginController {
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysPermissionService sysPermissionService;
@Autowired
private SysBaseApiImpl sysBaseApi;
@Autowired
private ISysLogService logService;
@Autowired
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysPermissionService sysPermissionService;
@Autowired
private SysBaseApiImpl sysBaseApi;
@Autowired
private ISysLogService logService;
@Autowired
private RedisUtil redisUtil;
@Autowired
@Autowired
private ISysDepartService sysDepartService;
@Autowired
private ISysTenantService sysTenantService;
@Autowired
@Autowired
private ISysTenantService sysTenantService;
@Autowired
private ISysDictService sysDictService;
@Resource
private BaseCommonService baseCommonService;
@Autowired
private JeecgBaseConfig jeecgBaseConfig;
private final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
@ApiOperation("登录接口")
@RequestMapping(value = "/login", method = RequestMethod.POST)
public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel){
Result<JSONObject> result = new Result<JSONObject>();
String username = sysLoginModel.getUsername();
String password = sysLoginModel.getPassword();
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
if(isLoginFailOvertimes(username)){
return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!");
}
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
//update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题
//前端密码加密,后端进行密码解密
//password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密
//update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题
//update-begin-author:taoyan date:20190828 for:校验验证码
@Resource
private BaseCommonService baseCommonService;
@Autowired
private JeecgBaseConfig jeecgBaseConfig;
private final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
@ApiOperation("登录接口")
@RequestMapping(value = "/login", method = RequestMethod.POST)
public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel) {
Result<JSONObject> result = new Result<JSONObject>();
String username = sysLoginModel.getUsername();
String password = sysLoginModel.getPassword();
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
if (isLoginFailOvertimes(username)) {
return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!");
}
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
//update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题
//前端密码加密,后端进行密码解密
//password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密
//update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题
//update-begin-author:taoyan date:20190828 for:校验验证码
String captcha = sysLoginModel.getCaptcha();
if(captcha==null){
if (captcha == null) {
result.error500("验证码无效");
return result;
}
String lowerCaseCaptcha = captcha.toLowerCase();
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
// 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可
String origin = lowerCaseCaptcha+sysLoginModel.getCheckKey()+jeecgBaseConfig.getSignatureSecret();
String realKey = Md5Util.md5Encode(origin, "utf-8");
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
Object checkCode = redisUtil.get(realKey);
//当进入登录页时,有一定几率出现验证码错误 #1714
if(checkCode==null || !checkCode.toString().equals(lowerCaseCaptcha)) {
// 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可
String origin = lowerCaseCaptcha + sysLoginModel.getCheckKey() + jeecgBaseConfig.getSignatureSecret();
String realKey = Md5Util.md5Encode(origin, "utf-8");
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
Object checkCode = redisUtil.get(realKey);
//当进入登录页时,有一定几率出现验证码错误 #1714
if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {
log.warn("验证码错误,key= {} , Ui checkCode= {}, Redis checkCode = {}", sysLoginModel.getCheckKey(), lowerCaseCaptcha, checkCode);
result.error500("验证码错误");
// 改成特殊的code 便于前端判断
result.setCode(HttpStatus.PRECONDITION_FAILED.value());
return result;
}
//update-end-author:taoyan date:20190828 for:校验验证码
//1. 校验用户是否有效
//update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getUsername,username);
SysUser sysUser = sysUserService.getOne(queryWrapper);
//update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
result = sysUserService.checkUserIsEffective(sysUser);
if(!result.isSuccess()) {
return result;
}
//2. 校验用户名或密码是否正确
String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
String syspassword = sysUser.getPassword();
if (!syspassword.equals(userpassword)) {
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
addLoginFailOvertimes(username);
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
result.error500("用户名或密码错误");
return result;
}
//用户登录信息
userInfo(sysUser, result);
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
redisUtil.del(realKey);
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
redisUtil.del(CommonConstant.LOGIN_FAIL + username);
LoginUser loginUser = new LoginUser();
BeanUtils.copyProperties(sysUser, loginUser);
baseCommonService.addLog("用户名: " + username + ",登录成功!", CommonConstant.LOG_TYPE_1, null,loginUser);
result.error500("验证码错误");
// 改成特殊的code 便于前端判断
result.setCode(HttpStatus.PRECONDITION_FAILED.value());
return result;
}
//update-end-author:taoyan date:20190828 for:校验验证码
//1. 校验用户是否有效
//update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getUsername, username);
SysUser sysUser = sysUserService.getOne(queryWrapper);
//update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
result = sysUserService.checkUserIsEffective(sysUser);
if (!result.isSuccess()) {
return result;
}
//2. 校验用户名或密码是否正确
String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
String syspassword = sysUser.getPassword();
if (!syspassword.equals(userpassword)) {
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
addLoginFailOvertimes(username);
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
result.error500("用户名或密码错误");
return result;
}
//用户登录信息
userInfo(sysUser, result);
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
redisUtil.del(realKey);
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
redisUtil.del(CommonConstant.LOGIN_FAIL + username);
LoginUser loginUser = new LoginUser();
BeanUtils.copyProperties(sysUser, loginUser);
baseCommonService.addLog("用户名: " + username + ",登录成功!", CommonConstant.LOG_TYPE_1, null, loginUser);
//update-end--Author:wangshuai Date:20200714 for:登录日志没有记录人员
return result;
}
/**
* 【vue3专用】获取用户信息
*/
@GetMapping("/user/getUserInfo")
public Result<JSONObject> getUserInfo(HttpServletRequest request){
Result<JSONObject> result = new Result<JSONObject>();
String username = JwtUtil.getUserNameByToken(request);
if(oConvertUtils.isNotEmpty(username)) {
// 根据用户名查询用户信息
SysUser sysUser = sysUserService.getUserByName(username);
JSONObject obj=new JSONObject();
//update-begin---author:scott ---date:2022-06-20 for:vue3前端,支持自定义首页-----------
String version = request.getHeader(CommonConstant.VERSION);
//update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
SysRoleIndex roleIndex = sysUserService.getDynamicIndexByUserRole(username, version);
if (oConvertUtils.isNotEmpty(version) && roleIndex != null && oConvertUtils.isNotEmpty(roleIndex.getUrl())) {
String homePath = roleIndex.getUrl();
if (!homePath.startsWith(SymbolConstant.SINGLE_SLASH)) {
homePath = SymbolConstant.SINGLE_SLASH + homePath;
}
sysUser.setHomePath(homePath);
}
//update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
//update-end---author:scott ---date::2022-06-20 for:vue3前端,支持自定义首页--------------
obj.put("userInfo",sysUser);
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
result.setResult(obj);
result.success("");
}
return result;
}
/**
* 退出登录
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/logout")
public Result<Object> logout(HttpServletRequest request,HttpServletResponse response) {
//用户退出逻辑
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
if(oConvertUtils.isEmpty(token)) {
return Result.error("退出登录失败!");
}
String username = JwtUtil.getUsername(token);
LoginUser sysUser = sysBaseApi.getUserByName(username);
if(sysUser!=null) {
//update-begin--Author:wangshuai Date:20200714 for:登出日志没有记录人员
baseCommonService.addLog("用户名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null,sysUser);
//update-end--Author:wangshuai Date:20200714 for:登出日志没有记录人员
log.info(" 用户名: "+sysUser.getRealname()+",退出成功! ");
//清空用户登录Token缓存
redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
//清空用户登录Shiro权限缓存
redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
//清空用户的缓存信息(包括部门信息),例如sys:cache:user::<username>
redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
//调用shiro的logout
SecurityUtils.getSubject().logout();
return Result.ok("退出登录成功!");
}else {
return Result.error("Token无效!");
}
}
/**
* 获取访问量
* @return
*/
@GetMapping("loginfo")
public Result<JSONObject> loginfo() {
Result<JSONObject> result = new Result<JSONObject>();
JSONObject obj = new JSONObject();
//update-begin--Author:zhangweijian Date:20190428 for:传入开始时间,结束时间参数
// 获取一天的开始和结束时间
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date dayStart = calendar.getTime();
calendar.add(Calendar.DATE, 1);
Date dayEnd = calendar.getTime();
// 获取系统访问记录
Long totalVisitCount = logService.findTotalVisitCount();
obj.put("totalVisitCount", totalVisitCount);
Long todayVisitCount = logService.findTodayVisitCount(dayStart,dayEnd);
obj.put("todayVisitCount", todayVisitCount);
Long todayIp = logService.findTodayIp(dayStart,dayEnd);
//update-end--Author:zhangweijian Date:20190428 for:传入开始时间,结束时间参数
obj.put("todayIp", todayIp);
result.setResult(obj);
result.success("登录成功");
return result;
}
/**
* 获取访问量
* @return
*/
@GetMapping("visitInfo")
public Result<List<Map<String,Object>>> visitInfo() {
Result<List<Map<String,Object>>> result = new Result<List<Map<String,Object>>>();
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.HOUR_OF_DAY,0);
calendar.set(Calendar.MINUTE,0);
calendar.set(Calendar.SECOND,0);
calendar.set(Calendar.MILLISECOND,0);
return result;
}
/**
* 【vue3专用】获取用户信息
*/
@GetMapping("/user/getUserInfo")
public Result<JSONObject> getUserInfo(HttpServletRequest request) {
Result<JSONObject> result = new Result<JSONObject>();
String username = JwtUtil.getUserNameByToken(request);
if (oConvertUtils.isNotEmpty(username)) {
// 根据用户名查询用户信息
SysUser sysUser = sysUserService.getUserByName(username);
JSONObject obj = new JSONObject();
//update-begin---author:scott ---date:2022-06-20 for:vue3前端,支持自定义首页-----------
String version = request.getHeader(CommonConstant.VERSION);
//update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
SysRoleIndex roleIndex = sysUserService.getDynamicIndexByUserRole(username, version);
if (oConvertUtils.isNotEmpty(version) && roleIndex != null && oConvertUtils.isNotEmpty(roleIndex.getUrl())) {
String homePath = roleIndex.getUrl();
if (!homePath.startsWith(SymbolConstant.SINGLE_SLASH)) {
homePath = SymbolConstant.SINGLE_SLASH + homePath;
}
sysUser.setHomePath(homePath);
}
//update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
//update-end---author:scott ---date::2022-06-20 for:vue3前端,支持自定义首页--------------
obj.put("userInfo", sysUser);
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
result.setResult(obj);
result.success("");
}
return result;
}
/**
* 退出登录
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/logout")
public Result<Object> logout(HttpServletRequest request, HttpServletResponse response) {
//用户退出逻辑
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
if (oConvertUtils.isEmpty(token)) {
return Result.error("退出登录失败!");
}
String username = JwtUtil.getUsername(token);
LoginUser sysUser = sysBaseApi.getUserByName(username);
if (sysUser != null) {
//update-begin--Author:wangshuai Date:20200714 for:登出日志没有记录人员
baseCommonService.addLog("用户名: " + sysUser.getRealname() + ",退出成功!", CommonConstant.LOG_TYPE_1, null, sysUser);
//update-end--Author:wangshuai Date:20200714 for:登出日志没有记录人员
log.info(" 用户名: " + sysUser.getRealname() + ",退出成功! ");
//清空用户登录Token缓存
redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
//清空用户登录Shiro权限缓存
redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
//清空用户的缓存信息(包括部门信息),例如sys:cache:user::<username>
redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
//调用shiro的logout
SecurityUtils.getSubject().logout();
return Result.ok("退出登录成功!");
} else {
return Result.error("Token无效!");
}
}
/**
* 获取访问量
*
* @return
*/
@GetMapping("loginfo")
public Result<JSONObject> loginfo() {
Result<JSONObject> result = new Result<JSONObject>();
JSONObject obj = new JSONObject();
//update-begin--Author:zhangweijian Date:20190428 for:传入开始时间,结束时间参数
// 获取一天的开始和结束时间
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date dayStart = calendar.getTime();
calendar.add(Calendar.DATE, 1);
Date dayEnd = calendar.getTime();
// 获取系统访问记录
Long totalVisitCount = logService.findTotalVisitCount();
obj.put("totalVisitCount", totalVisitCount);
Long todayVisitCount = logService.findTodayVisitCount(dayStart, dayEnd);
obj.put("todayVisitCount", todayVisitCount);
Long todayIp = logService.findTodayIp(dayStart, dayEnd);
//update-end--Author:zhangweijian Date:20190428 for:传入开始时间,结束时间参数
obj.put("todayIp", todayIp);
result.setResult(obj);
result.success("登录成功");
return result;
}
/**
* 获取访问量
*
* @return
*/
@GetMapping("visitInfo")
public Result<List<Map<String, Object>>> visitInfo() {
Result<List<Map<String, Object>>> result = new Result<List<Map<String, Object>>>();
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.add(Calendar.DAY_OF_MONTH, 1);
Date dayEnd = calendar.getTime();
calendar.add(Calendar.DAY_OF_MONTH, -7);
Date dayStart = calendar.getTime();
List<Map<String,Object>> list = logService.findVisitCount(dayStart, dayEnd);
result.setResult(oConvertUtils.toLowerCasePageList(list));
return result;
}
/**
* 登陆成功选择用户当前部门
* @param user
* @return
*/
@RequestMapping(value = "/selectDepart", method = RequestMethod.PUT)
public Result<JSONObject> selectDepart(@RequestBody SysUser user) {
Result<JSONObject> result = new Result<JSONObject>();
String username = user.getUsername();
if(oConvertUtils.isEmpty(username)) {
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
username = sysUser.getUsername();
}
//获取登录部门
String orgCode= user.getOrgCode();
//获取登录租户
Integer tenantId = user.getLoginTenantId();
this.sysUserService.updateUserDepart(username, orgCode,tenantId);
SysUser sysUser = sysUserService.getUserByName(username);
JSONObject obj = new JSONObject();
obj.put("userInfo", sysUser);
result.setResult(obj);
return result;
}
/**
* 短信登录接口
*
* @param jsonObject
* @return
*/
@PostMapping(value = "/sms")
public Result<String> sms(@RequestBody JSONObject jsonObject) {
Result<String> result = new Result<String>();
String mobile = jsonObject.get("mobile").toString();
//手机号模式 登录模式: "2" 注册模式: "1"
String smsmode=jsonObject.get("smsmode").toString();
log.info(mobile);
if(oConvertUtils.isEmpty(mobile)){
result.setMessage("手机号不允许为空!");
result.setSuccess(false);
return result;
}
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+mobile;
Object object = redisUtil.get(redisKey);
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
if (object != null) {
result.setMessage("验证码10分钟内,仍然有效!");
result.setSuccess(false);
return result;
}
//随机数
String captcha = RandomUtil.randomNumbers(6);
JSONObject obj = new JSONObject();
obj.put("code", captcha);
try {
boolean b = false;
//注册模板
if (CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)) {
SysUser sysUser = sysUserService.getUserByPhone(mobile);
if(sysUser!=null) {
result.error500(" 手机号已经注册,请直接登录!");
baseCommonService.addLog("手机号已经注册,请直接登录!", CommonConstant.LOG_TYPE_1, null);
return result;
}
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.REGISTER_TEMPLATE_CODE);
}else {
//登录模式,校验用户有效性
SysUser sysUser = sysUserService.getUserByPhone(mobile);
result = sysUserService.checkUserIsEffective(sysUser);
if(!result.isSuccess()) {
String message = result.getMessage();
String userNotExist="该用户不存在,请注册";
if(userNotExist.equals(message)){
result.error500("该用户不存在或未绑定手机号");
}
return result;
}
/**
* smsmode 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板
*/
if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {
//登录模板
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
} else if(CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {
//忘记密码模板
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
}
}
if (b == false) {
result.setMessage("短信验证码发送失败,请稍后重试");
result.setSuccess(false);
return result;
}
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
//验证码10分钟内有效
redisUtil.set(redisKey, captcha, 600);
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
//update-begin--Author:scott Date:20190812 for:issues#391
//result.setResult(captcha);
//update-end--Author:scott Date:20190812 for:issues#391
result.setSuccess(true);
} catch (ClientException e) {
e.printStackTrace();
result.error500(" 短信接口未配置,请联系管理员!");
return result;
}
return result;
}
/**
* 手机号登录接口
*
* @param jsonObject
* @return
*/
@ApiOperation("手机号登录接口")
@PostMapping("/phoneLogin")
public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject) {
Result<JSONObject> result = new Result<JSONObject>();
String phone = jsonObject.getString("mobile");
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
if(isLoginFailOvertimes(phone)){
return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!");
}
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
//校验用户有效性
SysUser sysUser = sysUserService.getUserByPhone(phone);
result = sysUserService.checkUserIsEffective(sysUser);
if(!result.isSuccess()) {
return result;
}
String smscode = jsonObject.getString("captcha");
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone;
Object code = redisUtil.get(redisKey);
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
if (!smscode.equals(code)) {
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
addLoginFailOvertimes(phone);
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
result.setMessage("手机验证码错误");
return result;
}
//用户信息
userInfo(sysUser, result);
//添加日志
baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功!", CommonConstant.LOG_TYPE_1, null);
return result;
}
/**
* 用户信息
*
* @param sysUser
* @param result
* @return
*/
private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
String username = sysUser.getUsername();
String syspassword = sysUser.getPassword();
// 获取用户部门信息
JSONObject obj = new JSONObject(new LinkedHashMap<>());
//1.生成token
String token = JwtUtil.sign(username, syspassword);
// 设置token缓存有效时间
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
obj.put("token", token);
//2.设置登录租户
Result<JSONObject> loginTenantError = sysUserService.setLoginTenant(sysUser, obj, username,result);
if (loginTenantError != null) {
return loginTenantError;
}
//3.设置登录用户信息
obj.put("userInfo", sysUser);
//4.设置登录部门
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
obj.put("departs", departs);
if (departs == null || departs.size() == 0) {
obj.put("multi_depart", 0);
} else if (departs.size() == 1) {
sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(),null);
obj.put("multi_depart", 1);
} else {
//查询当前是否有登录部门
// update-begin--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
SysUser sysUserById = sysUserService.getById(sysUser.getId());
if(oConvertUtils.isEmpty(sysUserById.getOrgCode())){
sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(),null);
}
// update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
obj.put("multi_depart", 2);
}
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
result.setResult(obj);
result.success("登录成功");
return result;
}
/**
* 获取加密字符串
* @return
*/
@GetMapping(value = "/getEncryptedString")
public Result<Map<String,String>> getEncryptedString(){
Result<Map<String,String>> result = new Result<Map<String,String>>();
Map<String,String> map = new HashMap(5);
map.put("key", EncryptedString.key);
map.put("iv",EncryptedString.iv);
result.setResult(map);
return result;
}
/**
* 后台生成图形验证码 :有效
* @param response
* @param key
*/
@ApiOperation("获取验证码")
@GetMapping(value = "/randomImage/{key}")
public Result<String> randomImage(HttpServletResponse response,@PathVariable("key") String key){
Result<String> res = new Result<String>();
try {
//生成验证码
String code = RandomUtil.randomString(BASE_CHECK_CODES,4);
//存到redis中
String lowerCaseCode = code.toLowerCase();
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
// 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可
String origin = lowerCaseCode+key+jeecgBaseConfig.getSignatureSecret();
String realKey = Md5Util.md5Encode(origin, "utf-8");
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
redisUtil.set(realKey, lowerCaseCode, 60);
log.info("获取验证码,Redis key = {},checkCode = {}", realKey, code);
//返回前端
String base64 = RandImageUtil.generate(code);
res.setSuccess(true);
res.setResult(base64);
} catch (Exception e) {
log.error(e.getMessage(), e);
res.error500("获取验证码失败,请检查redis配置!");
return res;
}
return res;
}
/**
* 切换菜单表为vue3的表
*/
@RequiresRoles({"admin"})
@GetMapping(value = "/switchVue3Menu")
public Result<String> switchVue3Menu(HttpServletResponse response) {
Result<String> res = new Result<String>();
sysPermissionService.switchVue3Menu();
return res;
}
/**
* app登录
* @param sysLoginModel
* @return
* @throws Exception
*/
@RequestMapping(value = "/mLogin", method = RequestMethod.POST)
public Result<JSONObject> mLogin(@RequestBody SysLoginModel sysLoginModel) throws Exception {
Result<JSONObject> result = new Result<JSONObject>();
String username = sysLoginModel.getUsername();
String password = sysLoginModel.getPassword();
JSONObject obj = new JSONObject();
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
if(isLoginFailOvertimes(username)){
return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!");
}
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
//1. 校验用户是否有效
SysUser sysUser = sysUserService.getUserByName(username);
result = sysUserService.checkUserIsEffective(sysUser);
if(!result.isSuccess()) {
return result;
}
//2. 校验用户名或密码是否正确
String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
String syspassword = sysUser.getPassword();
if (!syspassword.equals(userpassword)) {
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
addLoginFailOvertimes(username);
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
result.error500("用户名或密码错误");
return result;
}
//3.设置登录部门
String orgCode = sysUser.getOrgCode();
if(oConvertUtils.isEmpty(orgCode)) {
//如果当前用户无选择部门 查看部门关联信息
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
//update-begin-author:taoyan date:20220117 for: JTC-1068【app】新建用户,没有设置部门及角色,点击登录提示暂未归属部,一直在登录页面 使用手机号登录 可正常
if (departs == null || departs.size() == 0) {
List<Map<String, Object>> list = logService.findVisitCount(dayStart, dayEnd);
result.setResult(oConvertUtils.toLowerCasePageList(list));
return result;
}
/**
* 登陆成功选择用户当前部门
*
* @param user
* @return
*/
@RequestMapping(value = "/selectDepart", method = RequestMethod.PUT)
public Result<JSONObject> selectDepart(@RequestBody SysUser user) {
Result<JSONObject> result = new Result<JSONObject>();
String username = user.getUsername();
if (oConvertUtils.isEmpty(username)) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
username = sysUser.getUsername();
}
//获取登录部门
String orgCode = user.getOrgCode();
//获取登录租户
Integer tenantId = user.getLoginTenantId();
this.sysUserService.updateUserDepart(username, orgCode, tenantId);
SysUser sysUser = sysUserService.getUserByName(username);
JSONObject obj = new JSONObject();
obj.put("userInfo", sysUser);
result.setResult(obj);
return result;
}
/**
* 短信登录接口
*
* @param jsonObject
* @return
*/
@PostMapping(value = "/sms")
public Result<String> sms(@RequestBody JSONObject jsonObject) {
Result<String> result = new Result<String>();
String mobile = jsonObject.get("mobile").toString();
//手机号模式 登录模式: "2" 注册模式: "1"
String smsmode = jsonObject.get("smsmode").toString();
log.info(mobile);
if (oConvertUtils.isEmpty(mobile)) {
result.setMessage("手机号不允许为空!");
result.setSuccess(false);
return result;
}
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE + mobile;
Object object = redisUtil.get(redisKey);
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
if (object != null) {
result.setMessage("验证码10分钟内,仍然有效!");
result.setSuccess(false);
return result;
}
//随机数
String captcha = RandomUtil.randomNumbers(6);
JSONObject obj = new JSONObject();
obj.put("code", captcha);
try {
boolean b = false;
//注册模板
if (CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)) {
SysUser sysUser = sysUserService.getUserByPhone(mobile);
if (sysUser != null) {
result.error500(" 手机号已经注册,请直接登录!");
baseCommonService.addLog("手机号已经注册,请直接登录!", CommonConstant.LOG_TYPE_1, null);
return result;
}
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.REGISTER_TEMPLATE_CODE);
} else {
//登录模式,校验用户有效性
SysUser sysUser = sysUserService.getUserByPhone(mobile);
result = sysUserService.checkUserIsEffective(sysUser);
if (!result.isSuccess()) {
String message = result.getMessage();
String userNotExist = "该用户不存在,请注册";
if (userNotExist.equals(message)) {
result.error500("该用户不存在或未绑定手机号");
}
return result;
}
/**
* smsmode 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板
*/
if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {
//登录模板
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
} else if (CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {
//忘记密码模板
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
}
}
if (b == false) {
result.setMessage("短信验证码发送失败,请稍后重试");
result.setSuccess(false);
return result;
}
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
//验证码10分钟内有效
redisUtil.set(redisKey, captcha, 600);
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
//update-begin--Author:scott Date:20190812 for:issues#391
//result.setResult(captcha);
//update-end--Author:scott Date:20190812 for:issues#391
result.setSuccess(true);
} catch (ClientException e) {
e.printStackTrace();
result.error500(" 短信接口未配置,请联系管理员!");
return result;
}
return result;
}
/**
* 手机号登录接口
*
* @param jsonObject
* @return
*/
@ApiOperation("手机号登录接口")
@PostMapping("/phoneLogin")
public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject) {
Result<JSONObject> result = new Result<JSONObject>();
String phone = jsonObject.getString("mobile");
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
if (isLoginFailOvertimes(phone)) {
return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!");
}
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
//校验用户有效性
SysUser sysUser = sysUserService.getUserByPhone(phone);
result = sysUserService.checkUserIsEffective(sysUser);
if (!result.isSuccess()) {
return result;
}
String smscode = jsonObject.getString("captcha");
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE + phone;
Object code = redisUtil.get(redisKey);
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
if (!smscode.equals(code)) {
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
addLoginFailOvertimes(phone);
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
result.setMessage("手机验证码错误");
return result;
}
//用户信息
userInfo(sysUser, result);
//添加日志
baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功!", CommonConstant.LOG_TYPE_1, null);
return result;
}
/**
* 用户信息
*
* @param sysUser
* @param result
* @return
*/
private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
String username = sysUser.getUsername();
String syspassword = sysUser.getPassword();
// 获取用户部门信息
JSONObject obj = new JSONObject(new LinkedHashMap<>());
//1.生成token
String token = JwtUtil.sign(username, syspassword);
// 设置token缓存有效时间
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
obj.put("token", token);
//2.设置登录租户
Result<JSONObject> loginTenantError = sysUserService.setLoginTenant(sysUser, obj, username, result);
if (loginTenantError != null) {
return loginTenantError;
}
//3.设置登录用户信息
obj.put("userInfo", sysUser);
//4.设置登录部门
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
obj.put("departs", departs);
if (departs == null || departs.size() == 0) {
obj.put("multi_depart", 0);
} else if (departs.size() == 1) {
sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(), null);
obj.put("multi_depart", 1);
} else {
//查询当前是否有登录部门
// update-begin--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
SysUser sysUserById = sysUserService.getById(sysUser.getId());
if (oConvertUtils.isEmpty(sysUserById.getOrgCode())) {
sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(), null);
}
// update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
obj.put("multi_depart", 2);
}
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
result.setResult(obj);
result.success("登录成功");
return result;
}
/**
* 获取加密字符串
*
* @return
*/
@GetMapping(value = "/getEncryptedString")
public Result<Map<String, String>> getEncryptedString() {
Result<Map<String, String>> result = new Result<Map<String, String>>();
Map<String, String> map = new HashMap(5);
map.put("key", EncryptedString.key);
map.put("iv", EncryptedString.iv);
result.setResult(map);
return result;
}
/**
* 后台生成图形验证码 :有效
*
* @param response
* @param key
*/
@ApiOperation("获取验证码")
@GetMapping(value = "/randomImage/{key}")
public Result<String> randomImage(HttpServletResponse response, @PathVariable("key") String key) {
Result<String> res = new Result<String>();
try {
//生成验证码
String code = RandomUtil.randomString(BASE_CHECK_CODES, 4);
//存到redis中
String lowerCaseCode = code.toLowerCase();
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
// 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可
String origin = lowerCaseCode + key + jeecgBaseConfig.getSignatureSecret();
String realKey = Md5Util.md5Encode(origin, "utf-8");
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
redisUtil.set(realKey, lowerCaseCode, 60);
log.info("获取验证码,Redis key = {},checkCode = {}", realKey, code);
//返回前端
String base64 = RandImageUtil.generate(code);
res.setSuccess(true);
res.setCode(CommonConstant.SC_OK_200);
res.setResult(base64);
} catch (Exception e) {
log.error(e.getMessage(), e);
res.error500("获取验证码失败,请检查redis配置!");
return res;
}
return res;
}
/**
* 切换菜单表为vue3的表
*/
@RequiresRoles({"admin"})
@GetMapping(value = "/switchVue3Menu")
public Result<String> switchVue3Menu(HttpServletResponse response) {
Result<String> res = new Result<String>();
sysPermissionService.switchVue3Menu();
return res;
}
/**
* app登录
*
* @param sysLoginModel
* @return
* @throws Exception
*/
@RequestMapping(value = "/mLogin", method = RequestMethod.POST)
public Result<JSONObject> mLogin(@RequestBody SysLoginModel sysLoginModel) throws Exception {
Result<JSONObject> result = new Result<JSONObject>();
String username = sysLoginModel.getUsername();
String password = sysLoginModel.getPassword();
JSONObject obj = new JSONObject();
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
if (isLoginFailOvertimes(username)) {
return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!");
}
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
//1. 校验用户是否有效
SysUser sysUser = sysUserService.getUserByName(username);
result = sysUserService.checkUserIsEffective(sysUser);
if (!result.isSuccess()) {
return result;
}
//2. 校验用户名或密码是否正确
String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
String syspassword = sysUser.getPassword();
if (!syspassword.equals(userpassword)) {
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
addLoginFailOvertimes(username);
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
result.error500("用户名或密码错误");
return result;
}
//3.设置登录部门
String orgCode = sysUser.getOrgCode();
if (oConvertUtils.isEmpty(orgCode)) {
//如果当前用户无选择部门 查看部门关联信息
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
//update-begin-author:taoyan date:20220117 for: JTC-1068【app】新建用户,没有设置部门及角色,点击登录提示暂未归属部,一直在登录页面 使用手机号登录 可正常
if (departs == null || departs.size() == 0) {
/*result.error500("用户暂未归属部门,不可登录!");
return result;*/
}else{
orgCode = departs.get(0).getOrgCode();
sysUser.setOrgCode(orgCode);
this.sysUserService.updateUserDepart(username, orgCode,null);
}
//update-end-author:taoyan date:20220117 for: JTC-1068【app】新建用户,没有设置部门及角色,点击登录提示暂未归属部,一直在登录页面 使用手机号登录 可正常
}
//4. 设置登录租户
Result<JSONObject> loginTenantError = sysUserService.setLoginTenant(sysUser, obj, username, result);
if (loginTenantError != null) {
return loginTenantError;
}
//5. 设置登录用户信息
obj.put("userInfo", sysUser);
//6. 生成token
String token = JwtUtil.sign(username, syspassword);
// 设置超时时间
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);
//token 信息
obj.put("token", token);
result.setResult(obj);
result.setSuccess(true);
result.setCode(200);
baseCommonService.addLog("用户名: " + username + ",登录成功[移动端]!", CommonConstant.LOG_TYPE_1, null);
return result;
}
/**
* 图形验证码
* @param sysLoginModel
* @return
*/
@RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST)
public Result<?> checkCaptcha(@RequestBody SysLoginModel sysLoginModel){
String captcha = sysLoginModel.getCaptcha();
String checkKey = sysLoginModel.getCheckKey();
if(captcha==null){
return Result.error("验证码无效");
}
String lowerCaseCaptcha = captcha.toLowerCase();
String realKey = Md5Util.md5Encode(lowerCaseCaptcha+checkKey, "utf-8");
Object checkCode = redisUtil.get(realKey);
if(checkCode==null || !checkCode.equals(lowerCaseCaptcha)) {
return Result.error("验证码错误");
}
return Result.ok();
}
/**
* 登录二维码
*/
@ApiOperation(value = "登录二维码", notes = "登录二维码")
@GetMapping("/getLoginQrcode")
public Result<?> getLoginQrcode() {
String qrcodeId = CommonConstant.LOGIN_QRCODE_PRE+IdWorker.getIdStr();
//定义二维码参数
Map params = new HashMap(5);
params.put("qrcodeId", qrcodeId);
//存放二维码唯一标识30秒有效
redisUtil.set(CommonConstant.LOGIN_QRCODE + qrcodeId, qrcodeId, 30);
return Result.OK(params);
}
/**
* 扫码二维码
*/
@ApiOperation(value = "扫码登录二维码", notes = "扫码登录二维码")
@PostMapping("/scanLoginQrcode")
public Result<?> scanLoginQrcode(@RequestParam String qrcodeId, @RequestParam String token) {
Object check = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId);
if (oConvertUtils.isNotEmpty(check)) {
//存放token给前台读取
redisUtil.set(CommonConstant.LOGIN_QRCODE_TOKEN+qrcodeId, token, 60);
} else {
return Result.error("二维码已过期,请刷新后重试");
}
return Result.OK("扫码成功");
}
/**
* 获取用户扫码后保存的token
*/
@ApiOperation(value = "获取用户扫码后保存的token", notes = "获取用户扫码后保存的token")
@GetMapping("/getQrcodeToken")
public Result getQrcodeToken(@RequestParam String qrcodeId) {
Object token = redisUtil.get(CommonConstant.LOGIN_QRCODE_TOKEN + qrcodeId);
Map result = new HashMap(5);
Object qrcodeIdExpire = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId);
if (oConvertUtils.isEmpty(qrcodeIdExpire)) {
//二维码过期通知前台刷新
result.put("token", "-2");
return Result.OK(result);
}
if (oConvertUtils.isNotEmpty(token)) {
result.put("success", true);
result.put("token", token);
} else {
result.put("token", "-1");
}
return Result.OK(result);
}
/**
* 登录失败超出次数5 返回true
* @param username
* @return
*/
private boolean isLoginFailOvertimes(String username){
String key = CommonConstant.LOGIN_FAIL + username;
Object failTime = redisUtil.get(key);
if(failTime!=null){
Integer val = Integer.parseInt(failTime.toString());
if(val>5){
return true;
}
}
return false;
}
/**
* 记录登录失败次数
* @param username
*/
private void addLoginFailOvertimes(String username){
String key = CommonConstant.LOGIN_FAIL + username;
Object failTime = redisUtil.get(key);
Integer val = 0;
if(failTime!=null){
val = Integer.parseInt(failTime.toString());
}
// 1小时
redisUtil.set(key, ++val, 3600);
}
} else {
orgCode = departs.get(0).getOrgCode();
sysUser.setOrgCode(orgCode);
this.sysUserService.updateUserDepart(username, orgCode, null);
}
//update-end-author:taoyan date:20220117 for: JTC-1068【app】新建用户,没有设置部门及角色,点击登录提示暂未归属部,一直在登录页面 使用手机号登录 可正常
}
//4. 设置登录租户
Result<JSONObject> loginTenantError = sysUserService.setLoginTenant(sysUser, obj, username, result);
if (loginTenantError != null) {
return loginTenantError;
}
//5. 设置登录用户信息
obj.put("userInfo", sysUser);
//6. 生成token
String token = JwtUtil.sign(username, syspassword);
// 设置超时时间
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
//token 信息
obj.put("token", token);
result.setResult(obj);
result.setSuccess(true);
result.setCode(200);
baseCommonService.addLog("用户名: " + username + ",登录成功[移动端]!", CommonConstant.LOG_TYPE_1, null);
return result;
}
/**
* 图形验证码
*
* @param sysLoginModel
* @return
*/
@RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST)
public Result<?> checkCaptcha(@RequestBody SysLoginModel sysLoginModel) {
String captcha = sysLoginModel.getCaptcha();
String checkKey = sysLoginModel.getCheckKey();
if (captcha == null) {
return Result.error("验证码无效");
}
String lowerCaseCaptcha = captcha.toLowerCase();
String realKey = Md5Util.md5Encode(lowerCaseCaptcha + checkKey, "utf-8");
Object checkCode = redisUtil.get(realKey);
if (checkCode == null || !checkCode.equals(lowerCaseCaptcha)) {
return Result.error("验证码错误");
}
return Result.ok();
}
/**
* 登录二维码
*/
@ApiOperation(value = "登录二维码", notes = "登录二维码")
@GetMapping("/getLoginQrcode")
public Result<?> getLoginQrcode() {
String qrcodeId = CommonConstant.LOGIN_QRCODE_PRE + IdWorker.getIdStr();
//定义二维码参数
Map params = new HashMap(5);
params.put("qrcodeId", qrcodeId);
//存放二维码唯一标识30秒有效
redisUtil.set(CommonConstant.LOGIN_QRCODE + qrcodeId, qrcodeId, 30);
return Result.OK(params);
}
/**
* 扫码二维码
*/
@ApiOperation(value = "扫码登录二维码", notes = "扫码登录二维码")
@PostMapping("/scanLoginQrcode")
public Result<?> scanLoginQrcode(@RequestParam String qrcodeId, @RequestParam String token) {
Object check = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId);
if (oConvertUtils.isNotEmpty(check)) {
//存放token给前台读取
redisUtil.set(CommonConstant.LOGIN_QRCODE_TOKEN + qrcodeId, token, 60);
} else {
return Result.error("二维码已过期,请刷新后重试");
}
return Result.OK("扫码成功");
}
/**
* 获取用户扫码后保存的token
*/
@ApiOperation(value = "获取用户扫码后保存的token", notes = "获取用户扫码后保存的token")
@GetMapping("/getQrcodeToken")
public Result getQrcodeToken(@RequestParam String qrcodeId) {
Object token = redisUtil.get(CommonConstant.LOGIN_QRCODE_TOKEN + qrcodeId);
Map result = new HashMap(5);
Object qrcodeIdExpire = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId);
if (oConvertUtils.isEmpty(qrcodeIdExpire)) {
//二维码过期通知前台刷新
result.put("token", "-2");
return Result.OK(result);
}
if (oConvertUtils.isNotEmpty(token)) {
result.put("success", true);
result.put("token", token);
} else {
result.put("token", "-1");
}
return Result.OK(result);
}
/**
* 登录失败超出次数5 返回true
*
* @param username
* @return
*/
private boolean isLoginFailOvertimes(String username) {
String key = CommonConstant.LOGIN_FAIL + username;
Object failTime = redisUtil.get(key);
if (failTime != null) {
Integer val = Integer.parseInt(failTime.toString());
if (val > 5) {
return true;
}
}
return false;
}
/**
* 记录登录失败次数
*
* @param username
*/
private void addLoginFailOvertimes(String username) {
String key = CommonConstant.LOGIN_FAIL + username;
Object failTime = redisUtil.get(key);
Integer val = 0;
if (failTime != null) {
val = Integer.parseInt(failTime.toString());
}
// 1小时
redisUtil.set(key, ++val, 3600);
}
}
\ No newline at end of file
......@@ -131,7 +131,7 @@ spring:
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/hzsomms?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&zeroDateTimeBehavior=convertToNull
url: jdbc:mysql://47.94.207.62:3306/hzsomms2?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&zeroDateTimeBehavior=convertToNull
username: root
password: superAdmin&321
driver-class-name: com.mysql.jdbc.Driver
......@@ -144,7 +144,7 @@ spring:
#redis 配置
redis:
database: 0
host: 127.0.0.1
host: 47.94.207.62
lettuce:
pool:
max-active: 8 #最大连接数据库连接数,设 0 为没有限制
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment