Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in
Toggle navigation
H
hzsomms
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ZTGK
hzsomms
Commits
e325c69c
Commit
e325c69c
authored
Jun 21, 2023
by
hkl
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev-hkl' into 'master'
Dev hkl See merge request
!1
parents
66c23824
accfedad
Changes
31
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
1211 additions
and
1996 deletions
+1211
-1996
README.md
README.md
+0
-583
PageSearch.java
...re/src/main/java/org/jeecg/common/api/dto/PageSearch.java
+18
-0
Swagger2Config.java
...e-core/src/main/java/org/jeecg/config/Swagger2Config.java
+1
-2
JeecgTenantParser.java
...main/java/org/jeecg/config/mybatis/JeecgTenantParser.java
+0
-130
TenantContext.java
...src/main/java/org/jeecg/config/mybatis/TenantContext.java
+0
-25
ShiroConfig.java
...ore/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
+72
-72
LightRailController.java
...modules/subwayNetwork/controller/LightRailController.java
+19
-66
SectionStationMapController.java
...subwayNetwork/controller/SectionStationMapController.java
+0
-163
SubwaySectionController.java
...les/subwayNetwork/controller/SubwaySectionController.java
+5
-79
TrainStationController.java
...ules/subwayNetwork/controller/TrainStationController.java
+55
-141
LightRailQueryDTO.java
...rg/jeecg/modules/subwayNetwork/dto/LightRailQueryDTO.java
+16
-0
SubwaySectionDTO.java
...org/jeecg/modules/subwayNetwork/dto/SubwaySectionDTO.java
+16
-0
SubwaySectionEditDTO.java
...jeecg/modules/subwayNetwork/dto/SubwaySectionEditDTO.java
+10
-0
TrainStationQueryDTO.java
...jeecg/modules/subwayNetwork/dto/TrainStationQueryDTO.java
+21
-0
LightRail.java
...ava/org/jeecg/modules/subwayNetwork/entity/LightRail.java
+23
-27
TrainStation.java
.../org/jeecg/modules/subwayNetwork/entity/TrainStation.java
+14
-33
LightRailMapper.java
...g/jeecg/modules/subwayNetwork/mapper/LightRailMapper.java
+5
-1
TrainStationMapper.java
...eecg/modules/subwayNetwork/mapper/TrainStationMapper.java
+5
-0
LightRailMapper.xml
...eecg/modules/subwayNetwork/mapper/xml/LightRailMapper.xml
+28
-0
TrainStationMapper.xml
...g/modules/subwayNetwork/mapper/xml/TrainStationMapper.xml
+40
-0
ILightRailService.java
...eecg/modules/subwayNetwork/service/ILightRailService.java
+12
-1
ISubwaySectionService.java
.../modules/subwayNetwork/service/ISubwaySectionService.java
+2
-0
ITrainStationService.java
...g/modules/subwayNetwork/service/ITrainStationService.java
+7
-1
LightRailServiceImpl.java
...ules/subwayNetwork/service/impl/LightRailServiceImpl.java
+15
-3
SubwaySectionServiceImpl.java
.../subwayNetwork/service/impl/SubwaySectionServiceImpl.java
+6
-0
TrainStationServiceImpl.java
...s/subwayNetwork/service/impl/TrainStationServiceImpl.java
+11
-0
LightRailQueryVO.java
.../org/jeecg/modules/subwayNetwork/vo/LightRailQueryVO.java
+52
-0
SubwaySectionVO.java
...a/org/jeecg/modules/subwayNetwork/vo/SubwaySectionVO.java
+9
-0
TrainStationVO.java
...va/org/jeecg/modules/subwayNetwork/vo/TrainStationVO.java
+67
-0
LoginController.java
.../org/jeecg/modules/system/controller/LoginController.java
+680
-667
application-test.yml
...eecg-system-start/src/main/resources/application-test.yml
+2
-2
No files found.
README.md
View file @
e325c69c

JEECG BOOT 低代码开发平台
===============
当前最新版本: 3.5.1(发布日期:2023-04-20)
[

](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[

](http://www.jeecg.com)
[

](https://jeecg.blog.csdn.net)
[

](https://github.com/zhangdaiscott/jeecg-boot)
[

](https://github.com/zhangdaiscott/jeecg-boot)
[

](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走势图
[

](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、路由限流 √
#### 微服务架构图

### Jeecg Boot 产品功能蓝图

### 功能模块
```
├─系统管理
│ ├─用户管理
│ ├─角色管理
│ ├─菜单管理
│ ├─权限设置(支持按钮权限、数据权限)
│ ├─表单权限(控制字段禁用、隐藏)
│ ├─部门管理
│ ├─我的部门(二级管理员)
│ └─字典管理
│ └─分类字典
│ └─系统公告
│ └─职务管理
│ └─通讯录
│ └─多租户管理
├─消息中心
│ ├─消息管理
│ ├─模板管理
├─代码生成器(低代码)
│ ├─代码生成器功能(一键生成前后端代码,生成后无需修改直接用,绝对是后端开发福音)
│ ├─代码生成器模板(提供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端






##### 系统交互


##### 流程设计




##### 简版流程设计



##### 仪表盘设计器


##### 报表设计器




##### 表单设计器



##### 大屏设计器




##### UNIAPP效果


##### 零代码应用





##### 手机端


##### PAD端



##### 图表示例





##### 在线接口文档


## 捐赠
如果觉得还不错,请作者喝杯咖啡吧 ☺

\ No newline at end of file
jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/PageSearch.java
0 → 100644
View file @
e325c69c
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
;
}
jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java
View file @
e325c69c
...
...
@@ -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
();
...
...
jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/JeecgTenantParser.java
deleted
100644 → 0
View file @
66c23824
//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());
// });
// }
// }
//
//}
jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/TenantContext.java
deleted
100644 → 0
View file @
66c23824
//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();
// }
//}
jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
View file @
e325c69c
...
...
@@ -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"
);
...
...
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/controller/LightRailController.java
View file @
e325c69c
...
...
@@ -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
);
}
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/controller/SectionStationMapController.java
deleted
100644 → 0
View file @
66c23824
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
);
}
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/controller/SubwaySectionController.java
View file @
e325c69c
...
...
@@ -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
);
}
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/controller/TrainStationController.java
View file @
e325c69c
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
(
"批量删除成功!"
);
}
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/dto/LightRailQueryDTO.java
0 → 100644
View file @
e325c69c
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
;
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/dto/SubwaySectionDTO.java
0 → 100644
View file @
e325c69c
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
;
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/dto/SubwaySectionEditDTO.java
0 → 100644
View file @
e325c69c
package
org
.
jeecg
.
modules
.
subwayNetwork
.
dto
;
import
io.swagger.annotations.ApiModel
;
import
lombok.Data
;
@Data
@ApiModel
(
value
=
"SubwaySectionEditDTO编辑"
)
public
class
SubwaySectionEditDTO
{
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/dto/TrainStationQueryDTO.java
0 → 100644
View file @
e325c69c
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
;
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/entity/LightRail.java
View file @
e325c69c
...
...
@@ -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
;
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/entity/TrainStation.java
View file @
e325c69c
...
...
@@ -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
;
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/mapper/LightRailMapper.java
View file @
e325c69c
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
);
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/mapper/TrainStationMapper.java
View file @
e325c69c
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
);
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/mapper/xml/LightRailMapper.xml
View file @
e325c69c
...
...
@@ -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
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/mapper/xml/TrainStationMapper.xml
View file @
e325c69c
...
...
@@ -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
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/service/ILightRailService.java
View file @
e325c69c
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
);
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/service/ISubwaySectionService.java
View file @
e325c69c
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
);
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/service/ITrainStationService.java
View file @
e325c69c
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
);
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/service/impl/LightRailServiceImpl.java
View file @
e325c69c
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
;
}
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/service/impl/SubwaySectionServiceImpl.java
View file @
e325c69c
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
)
{
}
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/service/impl/TrainStationServiceImpl.java
View file @
e325c69c
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
());
}
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/vo/LightRailQueryVO.java
0 → 100644
View file @
e325c69c
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
;
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/vo/SubwaySectionVO.java
0 → 100644
View file @
e325c69c
package
org
.
jeecg
.
modules
.
subwayNetwork
.
vo
;
import
io.swagger.annotations.ApiModel
;
import
lombok.Data
;
@Data
@ApiModel
(
value
=
"区间VO"
)
public
class
SubwaySectionVO
{
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/subwayNetwork/vo/TrainStationVO.java
0 → 100644
View file @
e325c69c
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
;
}
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java
View file @
e325c69c
...
...
@@ -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
jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml
View file @
e325c69c
...
...
@@ -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 为没有限制
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment