mirror of https://github.com/jeecgboot/jeecg-boot
JeecgBoot 2.4.6版本发布
parent
c269d7637f
commit
a3695151dc
|
@ -1,13 +1,13 @@
|
|||
Jeecg-Boot 低代码开发平台
|
||||
===============
|
||||
|
||||
当前最新版本: 2.4.5(发布日期:20210607)
|
||||
当前最新版本: 2.4.6(发布日期:20210813)
|
||||
|
||||
|
||||
## 后端技术架构
|
||||
- 基础框架:Spring Boot 2.3.5.RELEASE
|
||||
|
||||
- 持久层框架:Mybatis-plus 3.4.1
|
||||
- 持久层框架:Mybatis-plus 3.4.3.1
|
||||
|
||||
- 安全框架:Apache Shiro 1.7.0,Jwt 3.11.0
|
||||
|
||||
|
@ -29,7 +29,7 @@ Jeecg-Boot 低代码开发平台
|
|||
|
||||
- 依赖管理:Maven
|
||||
|
||||
- 数据库:MySQL5.7+ & Oracle 11g
|
||||
- 数据库:MySQL5.7+ & Oracle 11g & SqlServer & postgresql
|
||||
|
||||
- 缓存:Redis
|
||||
|
||||
|
@ -43,7 +43,7 @@ Jeecg-Boot 低代码开发平台
|
|||
|
||||
- 常见问题: [http://jeecg.com/doc/qa](http://jeecg.com/doc/qa)
|
||||
|
||||
- QQ交流群 : ③816531124、①284271917、②769925425
|
||||
- QQ交流群 : ④774126647、③816531124、①284271917、②769925425
|
||||
|
||||
|
||||
## 专项文档
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-boot-base-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package org.jeecg.common.bpm.api;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.ServiceNameConstants;
|
||||
import org.jeecg.common.online.api.factory.OnlineBaseExtAPIFallbackFactory;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/**
|
||||
* 流程接口
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
@Component
|
||||
@FeignClient(contextId = "bpmBaseRemoteApi", value = ServiceNameConstants.SYSTEM_SERVICE,
|
||||
fallbackFactory = OnlineBaseExtAPIFallbackFactory.class)
|
||||
public interface IBpmBaseExtAPI {
|
||||
/**
|
||||
* 23. 流程提交接口(online,自定义开发)
|
||||
*
|
||||
* @param flowCode
|
||||
* 流程业务关联 例如:joa_leave_01
|
||||
* @param id
|
||||
* 表单业务数据data id
|
||||
* @param formUrl
|
||||
* 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile
|
||||
* 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username
|
||||
* 流程发起人账号
|
||||
* @param jsonData
|
||||
* Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostMapping(value = "/act/process/extActProcess/startMutilProcess")
|
||||
Result<String> startMutilProcess(@RequestParam("flowCode") String flowCode, @RequestParam("id") String id,
|
||||
@RequestParam("formUrl") String formUrl, @RequestParam("formUrlMobile") String formUrlMobile,
|
||||
@RequestParam("username") String username, @RequestParam("jsonData") String jsonData) throws Exception;
|
||||
|
||||
/**
|
||||
* 24. 流程提交接口(自定义表单设计器)
|
||||
*
|
||||
* @param flowCode
|
||||
* 流程业务关联 例如:joa_leave_01
|
||||
* @param id
|
||||
* 表单业务数据data id
|
||||
* @param formUrl
|
||||
* 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile
|
||||
* 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username
|
||||
* 流程发起人账号
|
||||
* @param jsonData
|
||||
* Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostMapping(value = "/act/process/extActProcess/startDesFormMutilProcess")
|
||||
Result<String> startDesFormMutilProcess(@RequestParam("flowCode") String flowCode, @RequestParam("id") String id,
|
||||
@RequestParam("formUrl") String formUrl, @RequestParam("formUrlMobile") String formUrlMobile,
|
||||
@RequestParam("username") String username, @RequestParam("jsonData") String jsonData) throws Exception;
|
||||
|
||||
/**
|
||||
* 25. 保存流程草稿箱接口(自定义开发表单、online表单)
|
||||
*
|
||||
* @param flowCode
|
||||
* 流程业务关联 例如:joa_leave_01
|
||||
* @param id
|
||||
* 表单业务数据data id
|
||||
* @param formUrl
|
||||
* 流程审批时附件页面默认展示的PC端表单组件(地址) 【非必填】
|
||||
* @param formUrlMobile
|
||||
* 流程审批时附件页面默认展示的移动端表单组件(地址) 【非必填】
|
||||
* @param username
|
||||
* 流程发起人账号
|
||||
* @param jsonData
|
||||
* Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostMapping(value = "/act/process/extActProcess/saveMutilProcessDraft")
|
||||
Result<String> saveMutilProcessDraft(@RequestParam("flowCode") String flowCode, @RequestParam("id") String id,
|
||||
@RequestParam("formUrl") String formUrl, @RequestParam("formUrlMobile") String formUrlMobile,
|
||||
@RequestParam("username") String username, @RequestParam("jsonData") String jsonData) throws Exception;
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package org.jeecg.common.bpm.api.factory;
|
||||
|
||||
import org.jeecg.common.bpm.api.IBpmBaseExtAPI;
|
||||
import org.jeecg.common.bpm.api.fallback.BpmBaseExtAPIFallback;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import feign.hystrix.FallbackFactory;
|
||||
|
||||
@Component
|
||||
public class BpmBaseExtAPIFallbackFactory implements FallbackFactory<IBpmBaseExtAPI> {
|
||||
|
||||
@Override
|
||||
public IBpmBaseExtAPI create(Throwable throwable) {
|
||||
BpmBaseExtAPIFallback fallback = new BpmBaseExtAPIFallback();
|
||||
fallback.setCause(throwable);
|
||||
return fallback;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.jeecg.common.bpm.api.fallback;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.bpm.api.IBpmBaseExtAPI;
|
||||
import org.jeecg.common.online.api.IOnlineBaseExtAPI;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 进入fallback的方法 检查是否token未设置
|
||||
*/
|
||||
@Slf4j
|
||||
public class BpmBaseExtAPIFallback implements IBpmBaseExtAPI {
|
||||
|
||||
@Setter
|
||||
private Throwable cause;
|
||||
|
||||
@Override
|
||||
public Result<String> startMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,
|
||||
String username, String jsonData) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> startDesFormMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,
|
||||
String username, String jsonData) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> saveMutilProcessDraft(String flowCode, String id, String formUrl, String formUrlMobile,
|
||||
String username, String jsonData) throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package org.jeecg.common.online.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.common.constant.ServiceNameConstants;
|
||||
import org.jeecg.common.online.api.factory.OnlineBaseExtAPIFallbackFactory;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 【Online】Feign API接口
|
||||
*/
|
||||
@Component
|
||||
@FeignClient(contextId = "onlineBaseRemoteApi", value = ServiceNameConstants.SYSTEM_ONLINE, fallbackFactory = OnlineBaseExtAPIFallbackFactory.class)
|
||||
public interface IOnlineBaseExtAPI {
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步新增
|
||||
*/
|
||||
@PostMapping(value = "/online/api/cgform/crazyForm/{name}")
|
||||
String cgformPostCrazyForm(@PathVariable("name") String tableName, @RequestBody JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步编辑
|
||||
*/
|
||||
@PutMapping(value = "/online/api/cgform/crazyForm/{name}")
|
||||
String cgformPutCrazyForm(@PathVariable("name") String tableName, @RequestBody JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* 通过online表名查询数据,同时查询出子表的数据
|
||||
*
|
||||
* @param tableName online表名
|
||||
* @param dataIds online数据ID
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/online/api/cgform/queryAllDataByTableName")
|
||||
JSONObject cgformQueryAllDataByTableName(@RequestParam("tableName") String tableName, @RequestParam("dataIds") String dataIds);
|
||||
|
||||
/**
|
||||
* online表单删除数据
|
||||
*
|
||||
* @param cgformCode Online表单code
|
||||
* @param dataIds 数据ID,可逗号分割
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping("/online/api/cgform/cgformDeleteDataByCode")
|
||||
String cgformDeleteDataByCode(@RequestParam("cgformCode") String cgformCode, @RequestParam("dataIds") String dataIds);
|
||||
|
||||
/**
|
||||
* 【cgreport】通过 head code 获取 sql语句,并执行该语句返回查询数据
|
||||
*
|
||||
* @param code 报表Code,如果没传ID就通过code查
|
||||
* @param forceKey
|
||||
* @param dataList
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/online/api/cgreportGetData")
|
||||
Map<String, Object> cgreportGetData(@RequestParam("code") String code, @RequestParam("forceKey") String forceKey, @RequestParam("dataList") String dataList);
|
||||
|
||||
/**
|
||||
* 【cgreport】对 cgreportGetData 的返回值做优化,封装 DictModel 集合
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/online/api/cgreportGetDataPackage")
|
||||
List<DictModel> cgreportGetDataPackage(@RequestParam("code") String code, @RequestParam("dictText") String dictText, @RequestParam("dictCode") String dictCode, @RequestParam("dataList") String dataList);
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.jeecg.common.online.api.factory;
|
||||
|
||||
import feign.hystrix.FallbackFactory;
|
||||
import org.jeecg.common.online.api.IOnlineBaseExtAPI;
|
||||
import org.jeecg.common.online.api.fallback.OnlineBaseExtAPIFallback;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class OnlineBaseExtAPIFallbackFactory implements FallbackFactory<IOnlineBaseExtAPI> {
|
||||
|
||||
@Override
|
||||
public IOnlineBaseExtAPI create(Throwable throwable) {
|
||||
OnlineBaseExtAPIFallback fallback = new OnlineBaseExtAPIFallback();
|
||||
fallback.setCause(throwable);
|
||||
return fallback;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package org.jeecg.common.online.api.fallback;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.online.api.IOnlineBaseExtAPI;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 进入fallback的方法 检查是否token未设置
|
||||
*/
|
||||
@Slf4j
|
||||
public class OnlineBaseExtAPIFallback implements IOnlineBaseExtAPI {
|
||||
|
||||
@Setter
|
||||
private Throwable cause;
|
||||
|
||||
@Override
|
||||
public String cgformPostCrazyForm(String tableName, JSONObject jsonObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cgformPutCrazyForm(String tableName, JSONObject jsonObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject cgformQueryAllDataByTableName(String tableName, String dataIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cgformDeleteDataByCode(String cgformCode, String dataIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> cgreportGetData(String code, String forceKey, String dataList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> cgreportGetDataPackage(String code, String dictText, String dictCode, String dataList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,10 +9,7 @@ import org.jeecg.common.system.api.factory.SysBaseAPIFallbackFactory;
|
|||
import org.jeecg.common.system.vo.*;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -109,6 +106,14 @@ public interface ISysBaseAPI extends CommonAPI {
|
|||
@GetMapping("/sys/api/queryDictItemsByCode")
|
||||
List<DictModel> queryDictItemsByCode(@RequestParam("code") String code);
|
||||
|
||||
/**
|
||||
* 获取有效的数据字典项
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryEnableDictItemsByCode")
|
||||
public List<DictModel> queryEnableDictItemsByCode(@RequestParam("code") String code);
|
||||
|
||||
/** 11查询所有的父级字典,按照create_time排序 */
|
||||
@GetMapping("/sys/api/queryAllDict")
|
||||
List<DictModel> queryAllDict();
|
||||
|
@ -385,30 +390,31 @@ public interface ISysBaseAPI extends CommonAPI {
|
|||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryUsersByUsernames")
|
||||
List<JSONObject> queryUsersByUsernames(String usernames);
|
||||
List<JSONObject> queryUsersByUsernames(@RequestParam("usernames") String usernames);
|
||||
|
||||
/**
|
||||
* 37根据多个用户ID(逗号分隔),查询返回多个用户信息
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryUsersByIds")
|
||||
List<JSONObject> queryUsersByIds(String ids);
|
||||
@RequestMapping("/sys/api/queryUsersByIds")
|
||||
List<JSONObject> queryUsersByIds(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 38根据多个部门编码(逗号分隔),查询返回多个部门信息
|
||||
* @param orgCodes
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryDepartsByOrgcodes")
|
||||
List<JSONObject> queryDepartsByOrgcodes(String orgCodes);
|
||||
@RequestMapping("/sys/api/queryDepartsByOrgcodes")
|
||||
List<JSONObject> queryDepartsByOrgcodes(@RequestParam("orgCodes") String orgCodes);
|
||||
|
||||
/**
|
||||
* 39根据多个部门编码(逗号分隔),查询返回多个部门信息
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryDepartsByOrgIds")
|
||||
List<JSONObject> queryDepartsByOrgIds(String ids);
|
||||
List<JSONObject> queryDepartsByOrgIds(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 40发送邮件消息
|
||||
|
@ -424,4 +430,81 @@ public interface ISysBaseAPI extends CommonAPI {
|
|||
*/
|
||||
@GetMapping("/sys/api/getDeptUserByOrgCode")
|
||||
List<Map> getDeptUserByOrgCode(@RequestParam("orgCode")String orgCode);
|
||||
|
||||
/**
|
||||
* 42 查询分类字典翻译
|
||||
*/
|
||||
@GetMapping("/sys/api/loadCategoryDictItem")
|
||||
List<String> loadCategoryDictItem(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 43 根据字典code加载字典text
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param keys 要查询的key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/loadDictItem")
|
||||
List<String> loadDictItem(@RequestParam("dictCode") String dictCode, @RequestParam("keys") String keys);
|
||||
|
||||
/**
|
||||
* 44 根据字典code查询字典项
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param dictCode 要查询的key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/getDictItems")
|
||||
List<DictModel> getDictItems(@RequestParam("dictCode") String dictCode);
|
||||
|
||||
/**
|
||||
* 45 根据多个字典code查询多个字典项
|
||||
*
|
||||
* @param dictCodeList
|
||||
* @return key = dictCode ; value=对应的字典项
|
||||
*/
|
||||
@RequestMapping("/sys/api/getManyDictItems")
|
||||
Map<String, List<DictModel>> getManyDictItems(@RequestParam("dictCodeList") List<String> dictCodeList);
|
||||
|
||||
/**
|
||||
* 46 【JSearchSelectTag下拉搜索组件专用接口】
|
||||
* 大数据量的字典表 走异步加载 即前端输入内容过滤数据
|
||||
*
|
||||
* @param dictCode 字典code格式:table,text,code
|
||||
* @param keyword 过滤关键字
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/loadDictItemByKeyword")
|
||||
List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize);
|
||||
|
||||
/**
|
||||
* 47 根据多个部门id(逗号分隔),查询返回多个部门信息
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryDepartsByIds")
|
||||
List<JSONObject> queryDepartsByIds(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 48 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割
|
||||
* @param dictCodes
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/sys/api/translateManyDict")
|
||||
Map<String, List<DictModel>> translateManyDict(@RequestParam("dictCodes") String dictCodes, @RequestParam("keys") String keys);
|
||||
|
||||
/**
|
||||
* 49 字典表的 翻译,可批量
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys 多个用逗号分割
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/sys/api/translateDictFromTableByKeys")
|
||||
List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys);
|
||||
|
||||
}
|
||||
|
|
|
@ -72,6 +72,11 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> queryEnableDictItemsByCode(String code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> queryAllDict() {
|
||||
return null;
|
||||
|
@ -255,6 +260,22 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
|||
public List<JSONObject> queryDepartsByOrgcodes(String orgCodes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JSONObject> queryDepartsByIds(String ids) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendEmailMsg(String email,String title,String content) {
|
||||
|
||||
|
@ -269,4 +290,29 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
|||
public List<JSONObject> queryDepartsByOrgIds(String ids) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> loadCategoryDictItem(String ids) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> loadDictItem(String dictCode, String keys) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> getDictItems(String dictCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<DictModel>> getManyDictItems(List<String> dictCodeList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
package org.jeecg.config;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer;
|
||||
import feign.Feign;
|
||||
import feign.Logger;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.Encoder;
|
||||
import feign.form.spring.SpringFormEncoder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.PathMatcherUtil;
|
||||
|
@ -33,12 +29,19 @@ import org.springframework.http.MediaType;
|
|||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer;
|
||||
|
||||
import feign.Feign;
|
||||
import feign.Logger;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.Encoder;
|
||||
import feign.form.spring.SpringFormEncoder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ConditionalOnClass(Feign.class)
|
||||
@AutoConfigureBefore(FeignAutoConfiguration.class)
|
||||
|
@ -52,13 +55,13 @@ public class FeignConfig {
|
|||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (null != attributes) {
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
log.info("Feign request: {}", request.getRequestURI());
|
||||
log.debug("Feign request: {}", request.getRequestURI());
|
||||
// 将token信息放入header中
|
||||
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
|
||||
if(token==null || "".equals(token)){
|
||||
token = request.getParameter("token");
|
||||
}
|
||||
log.info("Feign request token: {}", token);
|
||||
log.debug("Feign request token: {}", token);
|
||||
requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
|
||||
|
||||
//根据URL地址过滤请求 【字典表参数签名验证】
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-boot-base-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package org.jeecg.common.bpm.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
/**
|
||||
* 流程接口
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
public interface IBpmBaseExtAPI {
|
||||
/**
|
||||
* 23. 流程提交接口(online,自定义开发)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> startMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,String username, String jsonData) throws Exception;
|
||||
|
||||
/**
|
||||
* 24. 流程提交接口(自定义表单设计器)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> startDesFormMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,String username,String jsonData) throws Exception;
|
||||
/**
|
||||
* 25. 保存流程草稿箱接口(自定义开发表单、online表单)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址) 【非必填】
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址) 【非必填】
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> saveMutilProcessDraft(String flowCode, String id, String formUrl, String formUrlMobile,String username,String jsonData) throws Exception;
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package org.jeecg.common.online.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 表单设计器【Online】翻译API接口
|
||||
*
|
||||
* @author sunjianlei
|
||||
*/
|
||||
public interface IOnlineBaseExtAPI {
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步新增
|
||||
*/
|
||||
String cgformPostCrazyForm(String tableName, JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步编辑
|
||||
*/
|
||||
String cgformPutCrazyForm(String tableName, JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* online表单删除数据
|
||||
*
|
||||
* @param cgformCode Online表单code
|
||||
* @param dataIds 数据ID,可逗号分割
|
||||
* @return
|
||||
*/
|
||||
String cgformDeleteDataByCode(String cgformCode, String dataIds);
|
||||
|
||||
/**
|
||||
* 通过online表名查询数据,同时查询出子表的数据
|
||||
*
|
||||
* @param tableName online表名
|
||||
* @param dataIds online数据ID
|
||||
* @return
|
||||
*/
|
||||
JSONObject cgformQueryAllDataByTableName(String tableName, String dataIds);
|
||||
|
||||
/**
|
||||
* 对 cgreportGetData 的返回值做优化,封装 DictModel 集合
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> cgreportGetDataPackage(String code, String dictText, String dictCode, String dataList);
|
||||
|
||||
/**
|
||||
* 【cgreport】通过 head code 获取 sql语句,并执行该语句返回查询数据
|
||||
*
|
||||
* @param code 报表Code,如果没传ID就通过code查
|
||||
* @param forceKey
|
||||
* @param dataList
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> cgreportGetData(String code, String forceKey, String dataList);
|
||||
|
||||
}
|
|
@ -1,14 +1,11 @@
|
|||
package org.jeecg.common.system.api;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.jeecg.common.api.CommonAPI;
|
||||
import org.jeecg.common.api.dto.OnlineAuthDTO;
|
||||
import org.jeecg.common.api.dto.message.*;
|
||||
import org.jeecg.common.system.vo.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -289,4 +286,45 @@ public interface ISysBaseAPI extends CommonAPI {
|
|||
* @param orgCode
|
||||
*/
|
||||
List<Map> getDeptUserByOrgCode(String orgCode);
|
||||
|
||||
/**
|
||||
* 查询分类字典翻译
|
||||
*/
|
||||
List<String> loadCategoryDictItem(String ids);
|
||||
|
||||
/**
|
||||
* 根据字典code加载字典text
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param keys 要查询的key
|
||||
* @return
|
||||
*/
|
||||
List<String> loadDictItem(String dictCode, String keys);
|
||||
|
||||
/**
|
||||
* 根据字典code查询字典项
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param dictCode 要查询的key
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> getDictItems(String dictCode);
|
||||
|
||||
/**
|
||||
* 根据多个字典code查询多个字典项
|
||||
* @param dictCodeList
|
||||
* @return key = dictCode ; value=对应的字典项
|
||||
*/
|
||||
Map<String, List<DictModel>> getManyDictItems(List<String> dictCodeList);
|
||||
|
||||
/**
|
||||
* 【JSearchSelectTag下拉搜索组件专用接口】
|
||||
* 大数据量的字典表 走异步加载 即前端输入内容过滤数据
|
||||
*
|
||||
* @param dictCode 字典code格式:table,text,code
|
||||
* @param keyword 过滤关键字
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize);
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-boot-base</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-base</artifactId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
|||
<repository>
|
||||
<id>aliyun</id>
|
||||
<name>aliyun Repository</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
|
@ -22,7 +22,7 @@
|
|||
<repository>
|
||||
<id>jeecg</id>
|
||||
<name>jeecg Repository</name>
|
||||
<url>http://maven.jeecg.org/nexus/content/repositories/jeecg</url>
|
||||
<url>https://maven.jeecg.org/nexus/content/repositories/jeecg</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
|
@ -114,9 +114,10 @@
|
|||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>hibernate-re</artifactId>
|
||||
<version>2.4.5-RC</version>
|
||||
<version>2.4.6-beta</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据库驱动 -->
|
||||
<!--mysql-->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.jeecg.common.api;
|
|||
import org.jeecg.common.system.vo.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface CommonAPI {
|
||||
|
@ -85,6 +86,13 @@ public interface CommonAPI {
|
|||
*/
|
||||
public List<DictModel> queryDictItemsByCode(String code);
|
||||
|
||||
/**
|
||||
* 获取有效的数据字典项
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public List<DictModel> queryEnableDictItemsByCode(String code);
|
||||
|
||||
/**
|
||||
* 13获取表数据字典
|
||||
* @param table
|
||||
|
@ -94,4 +102,22 @@ public interface CommonAPI {
|
|||
*/
|
||||
List<DictModel> queryTableDictItemsByCode(String table, String text, String code);
|
||||
|
||||
/**
|
||||
* 14 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割
|
||||
* @param dictCodes 例如:user_status,sex
|
||||
* @param keys 例如:1,2,0
|
||||
* @return
|
||||
*/
|
||||
Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys);
|
||||
|
||||
/**
|
||||
* 15 字典表的 翻译,可批量
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys 多个用逗号分割
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.jeecg.common.aspect;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
@ -14,17 +15,17 @@ import org.jeecg.common.api.CommonAPI;
|
|||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Description: 字典aop类
|
||||
|
@ -56,7 +57,7 @@ public class DictAspect {
|
|||
long start=System.currentTimeMillis();
|
||||
this.parseDictText(result);
|
||||
long end=System.currentTimeMillis();
|
||||
log.debug("解析注入JSON数据 耗时"+(end-start)+"ms");
|
||||
log.debug("注入字典到JSON数据 耗时"+(end-start)+"ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -86,6 +87,12 @@ public class DictAspect {
|
|||
if (result instanceof Result) {
|
||||
if (((Result) result).getResult() instanceof IPage) {
|
||||
List<JSONObject> items = new ArrayList<>();
|
||||
|
||||
//step.1 筛选出加了 Dict 注解的字段列表
|
||||
List<Field> dictFieldList = new ArrayList<>();
|
||||
// 字典数据列表, key = 字典code,value=数据列表
|
||||
Map<String, List<String>> dataListMap = new HashMap<>();
|
||||
|
||||
for (Object record : ((IPage) ((Result) result).getResult()).getRecords()) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String json="{}";
|
||||
|
@ -98,20 +105,28 @@ public class DictAspect {
|
|||
JSONObject item = JSONObject.parseObject(json);
|
||||
//update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
|
||||
//for (Field field : record.getClass().getDeclaredFields()) {
|
||||
// 遍历所有字段,把字典Code取出来,放到 map 里
|
||||
for (Field field : oConvertUtils.getAllFields(record)) {
|
||||
String value = item.getString(field.getName());
|
||||
if (oConvertUtils.isEmpty(value)) {
|
||||
continue;
|
||||
}
|
||||
//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
|
||||
if (field.getAnnotation(Dict.class) != null) {
|
||||
if (!dictFieldList.contains(field)) {
|
||||
dictFieldList.add(field);
|
||||
}
|
||||
String code = field.getAnnotation(Dict.class).dicCode();
|
||||
String text = field.getAnnotation(Dict.class).dicText();
|
||||
String table = field.getAnnotation(Dict.class).dictTable();
|
||||
String key = String.valueOf(item.get(field.getName()));
|
||||
|
||||
//翻译字典值对应的txt
|
||||
String textValue = translateDictValue(code, text, table, key);
|
||||
|
||||
log.debug(" 字典Val : "+ textValue);
|
||||
log.debug(" __翻译字典字段__ "+field.getName() + CommonConstant.DICT_TEXT_SUFFIX+": "+ textValue);
|
||||
item.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);
|
||||
List<String> dataList;
|
||||
String dictCode = code;
|
||||
if (!StringUtils.isEmpty(table)) {
|
||||
dictCode = String.format("%s,%s,%s", table, text, code);
|
||||
}
|
||||
dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
|
||||
}
|
||||
//date类型默认转换string格式化日期
|
||||
if (field.getType().getName().equals("java.util.Date")&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
|
||||
|
@ -121,12 +136,194 @@ public class DictAspect {
|
|||
}
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
//step.2 调用翻译方法,一次性翻译
|
||||
Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap);
|
||||
|
||||
//step.3 将翻译结果填充到返回结果里
|
||||
for (JSONObject record : items) {
|
||||
for (Field field : dictFieldList) {
|
||||
String code = field.getAnnotation(Dict.class).dicCode();
|
||||
String text = field.getAnnotation(Dict.class).dicText();
|
||||
String table = field.getAnnotation(Dict.class).dictTable();
|
||||
|
||||
String fieldDictCode = code;
|
||||
if (!StringUtils.isEmpty(table)) {
|
||||
fieldDictCode = String.format("%s,%s,%s", table, text, code);
|
||||
}
|
||||
|
||||
String value = record.getString(field.getName());
|
||||
if (oConvertUtils.isNotEmpty(value)) {
|
||||
List<DictModel> dictModels = translText.get(fieldDictCode);
|
||||
if(dictModels==null || dictModels.size()==0){
|
||||
continue;
|
||||
}
|
||||
|
||||
String textValue = this.translDictText(dictModels, value);
|
||||
log.debug(" 字典Val : " + textValue);
|
||||
log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue);
|
||||
|
||||
// TODO-sun 测试输出,待删
|
||||
log.debug(" ---- dictCode: " + fieldDictCode);
|
||||
log.debug(" ---- value: " + value);
|
||||
log.debug(" ----- text: " + textValue);
|
||||
log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels));
|
||||
|
||||
record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
((IPage) ((Result) result).getResult()).setRecords(items);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list 去重添加
|
||||
*/
|
||||
private void listAddAllDeduplicate(List<String> dataList, List<String> addList) {
|
||||
// 筛选出dataList中没有的数据
|
||||
List<String> filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList());
|
||||
dataList.addAll(filterList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一次性把所有的字典都翻译了
|
||||
* 1. 所有的普通数据字典的所有数据只执行一次SQL
|
||||
* 2. 表字典相同的所有数据只执行一次SQL
|
||||
* @param dataListMap
|
||||
* @return
|
||||
*/
|
||||
private Map<String, List<DictModel>> translateAllDict(Map<String, List<String>> dataListMap) {
|
||||
// 翻译后的字典文本,key=dictCode
|
||||
Map<String, List<DictModel>> translText = new HashMap<>();
|
||||
// 需要翻译的数据(有些可以从redis缓存中获取,就不走数据库查询)
|
||||
List<String> needTranslData = new ArrayList<>();
|
||||
//step.1 先通过redis中获取缓存字典数据
|
||||
for (String dictCode : dataListMap.keySet()) {
|
||||
List<String> dataList = dataListMap.get(dictCode);
|
||||
if (dataList.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
// 表字典需要翻译的数据
|
||||
List<String> needTranslDataTable = new ArrayList<>();
|
||||
for (String s : dataList) {
|
||||
String data = s.trim();
|
||||
if (data.length() == 0) {
|
||||
continue; //跳过循环
|
||||
}
|
||||
if (dictCode.contains(",")) {
|
||||
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data);
|
||||
if (redisTemplate.hasKey(keyString)) {
|
||||
try {
|
||||
String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
list.add(new DictModel(data, text));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
} else if (!needTranslDataTable.contains(data)) {
|
||||
// 去重添加
|
||||
needTranslDataTable.add(data);
|
||||
}
|
||||
} else {
|
||||
String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data);
|
||||
if (redisTemplate.hasKey(keyString)) {
|
||||
try {
|
||||
String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
list.add(new DictModel(data, text));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
} else if (!needTranslData.contains(data)) {
|
||||
// 去重添加
|
||||
needTranslData.add(data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//step.2 调用数据库翻译表字典
|
||||
if (needTranslDataTable.size() > 0) {
|
||||
String[] arr = dictCode.split(",");
|
||||
String table = arr[0], text = arr[1], code = arr[2];
|
||||
String values = String.join(",", needTranslDataTable);
|
||||
log.info("translateDictFromTableByKeys.dictCode:" + dictCode);
|
||||
log.info("translateDictFromTableByKeys.values:" + values);
|
||||
List<DictModel> texts = commonAPI.translateDictFromTableByKeys(table, text, code, values);
|
||||
log.info("translateDictFromTableByKeys.result:" + texts);
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
list.addAll(texts);
|
||||
|
||||
// 做 redis 缓存
|
||||
for (DictModel dict : texts) {
|
||||
String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue());
|
||||
try {
|
||||
redisTemplate.opsForValue().set(redisKey, dict.getText());
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//step.3 调用数据库进行翻译普通字典
|
||||
if (needTranslData.size() > 0) {
|
||||
List<String> dictCodeList = Arrays.asList(dataListMap.keySet().toArray(new String[]{}));
|
||||
// 将不包含逗号的字典code筛选出来,因为带逗号的是表字典,而不是普通的数据字典
|
||||
List<String> filterDictCodes = dictCodeList.stream().filter(key -> !key.contains(",")).collect(Collectors.toList());
|
||||
String dictCodes = String.join(",", filterDictCodes);
|
||||
String values = String.join(",", needTranslData);
|
||||
log.info("translateManyDict.dictCodes:" + dictCodes);
|
||||
log.info("translateManyDict.values:" + values);
|
||||
Map<String, List<DictModel>> manyDict = commonAPI.translateManyDict(dictCodes, values);
|
||||
log.info("translateManyDict.result:" + manyDict);
|
||||
for (String dictCode : manyDict.keySet()) {
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
List<DictModel> newList = manyDict.get(dictCode);
|
||||
list.addAll(newList);
|
||||
|
||||
// 做 redis 缓存
|
||||
for (DictModel dict : newList) {
|
||||
String redisKey = String.format("sys:cache:dict::%s:%s", dictCode, dict.getValue());
|
||||
try {
|
||||
redisTemplate.opsForValue().set(redisKey, dict.getText());
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return translText;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典值替换文本
|
||||
*
|
||||
* @param dictModels
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
private String translDictText(List<DictModel> dictModels, String values) {
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
// 允许多个逗号分隔,允许传数组对象
|
||||
String[] splitVal = values.split(",");
|
||||
for (String val : splitVal) {
|
||||
String dictText = val;
|
||||
for (DictModel dict : dictModels) {
|
||||
if (val.equals(dict.getValue())) {
|
||||
dictText = dict.getText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.add(dictText);
|
||||
}
|
||||
return String.join(",", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译字典文本
|
||||
* @param code
|
||||
|
@ -135,6 +332,7 @@ public class DictAspect {
|
|||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
private String translateDictValue(String code, String text, String table, String key) {
|
||||
if(oConvertUtils.isEmpty(key)) {
|
||||
return null;
|
||||
|
|
|
@ -11,12 +11,14 @@ public interface DataBaseConstant {
|
|||
public static final String DB_TYPE_SQLSERVER = "SQLSERVER";
|
||||
public static final String DB_TYPE_MARIADB = "MARIADB";
|
||||
|
||||
// 数据库类型,对应 database_type 字典
|
||||
public static final String DB_TYPE_MYSQL_NUM = "1";
|
||||
public static final String DB_TYPE_ORACLE_NUM = "2";
|
||||
public static final String DB_TYPE_SQLSERVER_NUM = "3";
|
||||
public static final String DB_TYPE_POSTGRESQL_NUM = "4";
|
||||
public static final String DB_TYPE_MARIADB_NUM = "5";
|
||||
// // 数据库类型,对应 database_type 字典
|
||||
// public static final String DB_TYPE_MYSQL_NUM = "1";
|
||||
// public static final String DB_TYPE_MYSQL7_NUM = "6";
|
||||
// public static final String DB_TYPE_ORACLE_NUM = "2";
|
||||
// public static final String DB_TYPE_SQLSERVER_NUM = "3";
|
||||
// public static final String DB_TYPE_POSTGRESQL_NUM = "4";
|
||||
// public static final String DB_TYPE_MARIADB_NUM = "5";
|
||||
|
||||
//*********系统上下文变量****************************************
|
||||
/**
|
||||
* 数据-所属机构编码
|
||||
|
|
|
@ -29,6 +29,7 @@ public interface ServiceNameConstants {
|
|||
* 系统管理 admin
|
||||
*/
|
||||
String SYSTEM_SERVICE = "jeecg-system";
|
||||
String SYSTEM_ONLINE = "jeecg-online";
|
||||
|
||||
/**
|
||||
* gateway通过header传递根路径 basePath
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package org.jeecg.common.constant.enums;
|
||||
|
||||
/**
|
||||
* 首页自定义
|
||||
* 通过角色编码与首页组件路径配置
|
||||
*/
|
||||
public enum RoleIndexConfigEnum {
|
||||
/**
|
||||
* 管理员
|
||||
*/
|
||||
ADMIN("admin1", "dashboard/Analysis2"),
|
||||
/**
|
||||
* 测试
|
||||
*/
|
||||
TEST("test", "dashboard/Analysis"),
|
||||
/**
|
||||
* hr
|
||||
*/
|
||||
HR("hr", "dashboard/Analysis1");
|
||||
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
String roleCode;
|
||||
/**
|
||||
* 路由index
|
||||
*/
|
||||
String componentUrl;
|
||||
|
||||
/**
|
||||
* 构造器
|
||||
*
|
||||
* @param roleCode 角色编码
|
||||
* @param componentUrl 首页组件路径(规则跟菜单配置一样)
|
||||
*/
|
||||
RoleIndexConfigEnum(String roleCode, String componentUrl) {
|
||||
this.roleCode = roleCode;
|
||||
this.componentUrl = componentUrl;
|
||||
}
|
||||
/**
|
||||
* 根据code找枚举
|
||||
* @param roleCode 角色编码
|
||||
* @return
|
||||
*/
|
||||
public static RoleIndexConfigEnum getEnumByCode(String roleCode) {
|
||||
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
|
||||
if (e.roleCode.equals(roleCode)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 根据code找index
|
||||
* @param roleCode 角色编码
|
||||
* @return
|
||||
*/
|
||||
public static String getIndexByCode(String roleCode) {
|
||||
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
|
||||
if (e.roleCode.equals(roleCode)) {
|
||||
return e.componentUrl;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRoleCode() {
|
||||
return roleCode;
|
||||
}
|
||||
|
||||
public void setRoleCode(String roleCode) {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
public String getComponentUrl() {
|
||||
return componentUrl;
|
||||
}
|
||||
|
||||
public void setComponentUrl(String componentUrl) {
|
||||
this.componentUrl = componentUrl;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,8 @@ public class JeecgElasticsearchTemplate {
|
|||
/** es服务地址 */
|
||||
private String baseUrl;
|
||||
private final String FORMAT_JSON = "format=json";
|
||||
/** Elasticsearch 的版本号 */
|
||||
private String version = null;
|
||||
|
||||
// ElasticSearch 最大可返回条目数
|
||||
public static final int ES_MAX_SIZE = 10000;
|
||||
|
@ -37,15 +39,31 @@ public class JeecgElasticsearchTemplate {
|
|||
// 验证配置的ES地址是否有效
|
||||
if (checkEnabled) {
|
||||
try {
|
||||
RestUtil.get(this.getBaseUrl().toString());
|
||||
this.getElasticsearchVersion();
|
||||
log.info("ElasticSearch 服务连接成功");
|
||||
log.info("ElasticSearch version: " + this.version);
|
||||
} catch (Exception e) {
|
||||
this.version = "";
|
||||
log.warn("ElasticSearch 服务连接失败,原因:配置未通过。可能是BaseURL未配置或配置有误,也可能是Elasticsearch服务未启动。接下来将会拒绝执行任何方法!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Elasticsearch 的版本号信息,失败返回null
|
||||
*/
|
||||
private void getElasticsearchVersion() {
|
||||
if (this.version == null) {
|
||||
String url = this.getBaseUrl().toString();
|
||||
JSONObject result = RestUtil.get(url);
|
||||
if (result != null) {
|
||||
JSONObject v = result.getJSONObject("version");
|
||||
this.version = v.getString("number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public StringBuilder getBaseUrl(String indexName, String typeName) {
|
||||
typeName = typeName.trim().toLowerCase();
|
||||
return this.getBaseUrl(indexName).append("/").append(typeName);
|
||||
|
@ -185,6 +203,11 @@ public class JeecgElasticsearchTemplate {
|
|||
*/
|
||||
public JSONObject getIndexMapping(String indexName, String typeName) {
|
||||
String url = this.getBaseUrl(indexName, typeName).append("/_mapping?").append(FORMAT_JSON).toString();
|
||||
// 针对 es 7.x 版本做兼容
|
||||
this.getElasticsearchVersion();
|
||||
if (oConvertUtils.isNotEmpty(this.version) && this.version.startsWith("7")) {
|
||||
url += "&include_type_name=true";
|
||||
}
|
||||
log.info("getIndexMapping-url:" + url);
|
||||
/*
|
||||
* 参考返回JSON结构:
|
||||
|
|
|
@ -7,7 +7,13 @@ public class QueryCondition implements Serializable {
|
|||
private static final long serialVersionUID = 4740166316629191651L;
|
||||
|
||||
private String field;
|
||||
/** 组件的类型(例如:input、select、radio) */
|
||||
private String type;
|
||||
/**
|
||||
* 对应的数据库字段的类型
|
||||
* 支持:int、bigDecimal、short、long、float、double、boolean
|
||||
*/
|
||||
private String dbType;
|
||||
private String rule;
|
||||
private String val;
|
||||
|
||||
|
@ -27,6 +33,14 @@ public class QueryCondition implements Serializable {
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDbType() {
|
||||
return dbType;
|
||||
}
|
||||
|
||||
public void setDbType(String dbType) {
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
@ -49,7 +63,7 @@ public class QueryCondition implements Serializable {
|
|||
if(field == null || "".equals(field)){
|
||||
return "";
|
||||
}
|
||||
sb.append(this.field).append(" ").append(this.rule).append(" ").append(this.type).append(" ").append(this.val);
|
||||
sb.append(this.field).append(" ").append(this.rule).append(" ").append(this.type).append(" ").append(this.dbType).append(" ").append(this.val);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,5 @@
|
|||
package org.jeecg.common.system.query;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.beanutils.PropertyUtils;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.DataBaseConstant;
|
||||
import org.jeecg.common.system.util.JeecgDataAutorUtils;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.SysPermissionDataRuleModel;
|
||||
import org.jeecg.common.util.CommonUtils;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.SqlInjectionUtil;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.springframework.util.NumberUtils;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -28,6 +12,25 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.beanutils.PropertyUtils;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.DataBaseConstant;
|
||||
import org.jeecg.common.system.util.JeecgDataAutorUtils;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.SysPermissionDataRuleModel;
|
||||
import org.jeecg.common.util.CommonUtils;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.SqlInjectionUtil;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.springframework.util.NumberUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class QueryGenerator {
|
||||
public static final String SQL_RULES_COLUMN = "SQL_RULES_COLUMN";
|
||||
|
@ -238,12 +241,12 @@ public class QueryGenerator {
|
|||
//queryWrapper.orderByAsc(oConvertUtils.camelToUnderline(column));
|
||||
String columnStr = oConvertUtils.camelToUnderline(column);
|
||||
String[] columnArray = columnStr.split(",");
|
||||
queryWrapper.orderByAsc(columnArray);
|
||||
queryWrapper.orderByAsc(Arrays.asList(columnArray));
|
||||
} else {
|
||||
//queryWrapper.orderByDesc(oConvertUtils.camelToUnderline(column));
|
||||
String columnStr = oConvertUtils.camelToUnderline(column);
|
||||
String[] columnArray = columnStr.split(",");
|
||||
queryWrapper.orderByDesc(columnArray);
|
||||
queryWrapper.orderByDesc(Arrays.asList(columnArray));
|
||||
}
|
||||
//update-end--Author:scott Date:20210531 for:36 多条件排序无效问题修正-------
|
||||
}
|
||||
|
@ -284,6 +287,39 @@ public class QueryGenerator {
|
|||
}else if("datetime".equals(rule.getType())){
|
||||
queryValue = DateUtils.str2Date(rule.getVal(), DateUtils.datetimeFormat.get());
|
||||
}
|
||||
// update-begin--author:sunjianlei date:20210702 for:【/issues/I3VR8E】高级查询没有类型转换,查询参数都是字符串类型 ----
|
||||
String dbType = rule.getDbType();
|
||||
if (oConvertUtils.isNotEmpty(dbType)) {
|
||||
try {
|
||||
String valueStr = String.valueOf(queryValue);
|
||||
switch (dbType.toLowerCase().trim()) {
|
||||
case "int":
|
||||
queryValue = Integer.parseInt(valueStr);
|
||||
break;
|
||||
case "bigdecimal":
|
||||
queryValue = new BigDecimal(valueStr);
|
||||
break;
|
||||
case "short":
|
||||
queryValue = Short.parseShort(valueStr);
|
||||
break;
|
||||
case "long":
|
||||
queryValue = Long.parseLong(valueStr);
|
||||
break;
|
||||
case "float":
|
||||
queryValue = Float.parseFloat(valueStr);
|
||||
break;
|
||||
case "double":
|
||||
queryValue = Double.parseDouble(valueStr);
|
||||
break;
|
||||
case "boolean":
|
||||
queryValue = Boolean.parseBoolean(valueStr);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("高级查询值转换失败:", e);
|
||||
}
|
||||
}
|
||||
// update-begin--author:sunjianlei date:20210702 for:【/issues/I3VR8E】高级查询没有类型转换,查询参数都是字符串类型 ----
|
||||
addEasyQuery(andWrapper, fieldColumnMap.get(rule.getField()), QueryRuleEnum.getByValue(rule.getRule()), queryValue);
|
||||
//update-end-author:taoyan date:20201228 for: 【高级查询】 oracle 日期等于查询报错
|
||||
|
||||
|
@ -313,13 +349,15 @@ public class QueryGenerator {
|
|||
*/
|
||||
private static QueryRuleEnum convert2Rule(Object value) {
|
||||
// 避免空数据
|
||||
// update-begin-author:taoyan date:20210629 for: 查询条件输入空格导致return null后续判断导致抛出null异常
|
||||
if (value == null) {
|
||||
return null;
|
||||
return QueryRuleEnum.EQ;
|
||||
}
|
||||
String val = (value + "").toString().trim();
|
||||
if (val.length() == 0) {
|
||||
return null;
|
||||
return QueryRuleEnum.EQ;
|
||||
}
|
||||
// update-end-author:taoyan date:20210629 for: 查询条件输入空格导致return null后续判断导致抛出null异常
|
||||
QueryRuleEnum rule =null;
|
||||
|
||||
//update-begin--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------
|
||||
|
@ -820,20 +858,25 @@ public class QueryGenerator {
|
|||
}
|
||||
|
||||
private static String getInConditionValue(Object value,boolean isString) {
|
||||
//update-begin-author:taoyan date:20210628 for: 查询条件如果输入,导致sql报错
|
||||
String[] temp = value.toString().split(",");
|
||||
if(temp.length==0){
|
||||
return "('')";
|
||||
}
|
||||
if(isString) {
|
||||
String temp[] = value.toString().split(",");
|
||||
String res="";
|
||||
List<String> res = new ArrayList<>();
|
||||
for (String string : temp) {
|
||||
if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){
|
||||
res+=",N'"+string+"'";
|
||||
res.add("N'"+string+"'");
|
||||
}else{
|
||||
res+=",'"+string+"'";
|
||||
res.add("'"+string+"'");
|
||||
}
|
||||
}
|
||||
return "("+res.substring(1)+")";
|
||||
return "("+String.join("," ,res)+")";
|
||||
}else {
|
||||
return "("+value.toString()+")";
|
||||
}
|
||||
//update-end-author:taoyan date:20210628 for: 查询条件如果输入,导致sql报错
|
||||
}
|
||||
|
||||
private static String getLikeConditionValue(Object value) {
|
||||
|
@ -1003,8 +1046,6 @@ public class QueryGenerator {
|
|||
|
||||
|
||||
|
||||
/** 当前系统数据库类型 */
|
||||
private static String DB_TYPE;
|
||||
/**
|
||||
* 获取系统数据库类型
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package org.jeecg.common.system.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 查询多个字典时用到
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DictModelMany extends DictModel {
|
||||
|
||||
/**
|
||||
* 字典code,根据多个字段code查询时才用到,用于区分不同的字典选项
|
||||
*/
|
||||
private String dictCode;
|
||||
|
||||
}
|
|
@ -36,10 +36,12 @@ public class DynamicDataSourceModel {
|
|||
* 数据源地址
|
||||
*/
|
||||
private java.lang.String dbUrl;
|
||||
/**
|
||||
* 数据库名称
|
||||
*/
|
||||
private java.lang.String dbName;
|
||||
|
||||
// /**
|
||||
// * 数据库名称
|
||||
// */
|
||||
// private java.lang.String dbName;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
package org.jeecg.common.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.pinyin.PinyinUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.DataBaseConstant;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.util.oss.OssBootUtil;
|
||||
import org.jeecgframework.poi.util.PoiPublicUtil;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.DataBaseConstant;
|
||||
import org.jeecg.common.util.filter.FileTypeFilter;
|
||||
import org.jeecg.common.util.oss.OssBootUtil;
|
||||
import org.jeecgframework.poi.util.PoiPublicUtil;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class CommonUtils {
|
||||
|
||||
|
@ -116,6 +116,9 @@ public class CommonUtils {
|
|||
*/
|
||||
public static String uploadLocal(MultipartFile mf,String bizPath,String uploadpath){
|
||||
try {
|
||||
//update-begin-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
FileTypeFilter.fileTypeFilter(mf);
|
||||
//update-end-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
String fileName = null;
|
||||
File file = new File(uploadpath + File.separator + bizPath + File.separator );
|
||||
if (!file.exists()) {
|
||||
|
@ -143,6 +146,8 @@ public class CommonUtils {
|
|||
return dbpath;
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -163,6 +168,13 @@ public class CommonUtils {
|
|||
|
||||
/** 当前系统数据库类型 */
|
||||
private static String DB_TYPE = "";
|
||||
private static DbType dbTypeEnum = null;
|
||||
|
||||
/**
|
||||
* 全局获取平台数据库类型(作废了)
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static String getDatabaseType() {
|
||||
if(oConvertUtils.isNotEmpty(DB_TYPE)){
|
||||
return DB_TYPE;
|
||||
|
@ -177,6 +189,24 @@ public class CommonUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局获取平台数据库类型(对应mybaisPlus枚举)
|
||||
* @return
|
||||
*/
|
||||
public static DbType getDatabaseTypeEnum() {
|
||||
if (oConvertUtils.isNotEmpty(dbTypeEnum)) {
|
||||
return dbTypeEnum;
|
||||
}
|
||||
try {
|
||||
DataSource dataSource = SpringContextUtils.getApplicationContext().getBean(DataSource.class);
|
||||
dbTypeEnum = JdbcUtils.getDbType(dataSource.getConnection().getMetaData().getURL());
|
||||
return dbTypeEnum;
|
||||
} catch (SQLException e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库类型
|
||||
* @param dataSource
|
||||
|
|
|
@ -291,7 +291,7 @@ public class DateUtils extends PropertyEditorSupport {
|
|||
Date dt = new Date();
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String nowTime = df.format(dt);
|
||||
Timestamp buydate = Timestamp.valueOf(nowTime);
|
||||
java.sql.Timestamp buydate = java.sql.Timestamp.valueOf(nowTime);
|
||||
return buydate;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.jeecg.common.util;
|
|||
|
||||
import io.minio.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.util.filter.FileTypeFilter;
|
||||
import org.jeecg.common.util.filter.StrAttackFilter;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
|
@ -68,6 +69,9 @@ public class MinioUtil {
|
|||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build());
|
||||
log.info("create a new bucket.");
|
||||
}
|
||||
//update-begin-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
FileTypeFilter.fileTypeFilter(file);
|
||||
//update-end-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
InputStream stream = file.getInputStream();
|
||||
// 获取文件名
|
||||
String orgName = file.getOriginalFilename();
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package org.jeecg.common.util;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
/**
|
||||
* 使用Spring自身提供的地址匹配工具匹配URL
|
||||
*/
|
||||
|
|
|
@ -192,6 +192,23 @@ public class ReflectHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取属性值
|
||||
*/
|
||||
public static Object getFieldVal(String fieldName, Object o) {
|
||||
try {
|
||||
// 暴力反射获取属性
|
||||
Field filed = o.getClass().getDeclaredField(fieldName);
|
||||
// 设置反射时取消Java的访问检查,暴力访问
|
||||
filed.setAccessible(true);
|
||||
Object val = filed.get(o);
|
||||
return val;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取属性名数组
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package org.jeecg.common.util.dynamic.db;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
|
||||
/**
|
||||
* 数据库类型判断
|
||||
* 【有些数据库引擎是一样的,以达到复用目的】
|
||||
*/
|
||||
public class DbTypeUtils {
|
||||
|
||||
public static boolean dbTypeIsMySQL(DbType dbType) {
|
||||
return dbTypeIf(dbType, DbType.MYSQL, DbType.MARIADB, DbType.CLICK_HOUSE, DbType.SQLITE);
|
||||
}
|
||||
|
||||
public static boolean dbTypeIsOracle(DbType dbType) {
|
||||
return dbTypeIf(dbType, DbType.ORACLE, DbType.ORACLE_12C, DbType.DM);
|
||||
}
|
||||
|
||||
public static boolean dbTypeIsSQLServer(DbType dbType) {
|
||||
return dbTypeIf(dbType, DbType.SQL_SERVER, DbType.SQL_SERVER2005);
|
||||
}
|
||||
|
||||
public static boolean dbTypeIsPostgre(DbType dbType) {
|
||||
return dbTypeIf(dbType, DbType.POSTGRE_SQL, DbType.KINGBASE_ES, DbType.GAUSS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断数据库类型
|
||||
*/
|
||||
public static boolean dbTypeIf(DbType dbType, DbType... correctTypes) {
|
||||
for (DbType type : correctTypes) {
|
||||
if (type.equals(dbType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -49,7 +49,7 @@ public class DynamicDBUtil {
|
|||
dataSource.setBreakAfterAcquireFailure(true);
|
||||
dataSource.setConnectionErrorRetryAttempts(0);
|
||||
dataSource.setUsername(dbUser);
|
||||
dataSource.setMaxWait(60000);
|
||||
dataSource.setMaxWait(30000);
|
||||
dataSource.setPassword(dbPassword);
|
||||
|
||||
log.info("******************************************");
|
||||
|
@ -151,6 +151,7 @@ public class DynamicDBUtil {
|
|||
list = findList(dbKey, sql, param);
|
||||
if (oConvertUtils.listIsEmpty(list)) {
|
||||
log.error("Except one, but not find actually");
|
||||
return null;
|
||||
}
|
||||
if (list.size() > 1) {
|
||||
log.error("Except one, but more than one actually");
|
||||
|
|
|
@ -1,213 +0,0 @@
|
|||
package org.jeecg.common.util.dynamic.db;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.constant.DataBaseConstant;
|
||||
import org.jeecg.common.system.vo.DynamicDataSourceModel;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 根据不同的数据库,动态生成SQL,例如分页
|
||||
*/
|
||||
public class SqlUtils {
|
||||
|
||||
public static final String DATABSE_TYPE_MYSQL = "mysql";
|
||||
public static final String DATABSE_TYPE_MARIADB = "mariadb";
|
||||
public static final String DATABSE_TYPE_POSTGRE = "postgresql";
|
||||
public static final String DATABSE_TYPE_ORACLE = "oracle";
|
||||
public static final String DATABSE_TYPE_SQLSERVER = "sqlserver";
|
||||
|
||||
|
||||
/**
|
||||
* 分页SQL
|
||||
*/
|
||||
public static final String MYSQL_SQL = "select * from ( {0}) sel_tab00 limit {1},{2}";
|
||||
public static final String POSTGRE_SQL = "select * from ( {0}) sel_tab00 limit {2} offset {1}";
|
||||
public static final String ORACLE_SQL = "select * from (select row_.*,rownum rownum_ from ({0}) row_ where rownum <= {1}) where rownum_>{2}";
|
||||
public static final String SQLSERVER_SQL = "select * from ( select row_number() over(order by tempColumn) tempRowNumber, * from (select top {1} tempColumn = 0, {0}) t ) tt where tempRowNumber > {2}";
|
||||
|
||||
/**
|
||||
* 获取所有表的SQL
|
||||
*/
|
||||
public static final String MYSQL_ALLTABLES_SQL = "select distinct table_name from information_schema.columns where table_schema = {0}";
|
||||
public static final String POSTGRE__ALLTABLES_SQL = "SELECT distinct c.relname AS table_name FROM pg_class c";
|
||||
public static final String ORACLE__ALLTABLES_SQL = "select distinct colstable.table_name as table_name from user_tab_cols colstable";
|
||||
public static final String SQLSERVER__ALLTABLES_SQL = "select distinct c.name as table_name from sys.objects c";
|
||||
|
||||
/**
|
||||
* 获取指定表的所有列名
|
||||
*/
|
||||
public static final String MYSQL_ALLCOLUMNS_SQL = "select column_name from information_schema.columns where table_name = {0} and table_schema = {1}";
|
||||
public static final String POSTGRE_ALLCOLUMNS_SQL = "select table_name from information_schema.columns where table_name = {0}";
|
||||
public static final String ORACLE_ALLCOLUMNS_SQL = "select column_name from all_tab_columns where table_name ={0}";
|
||||
public static final String SQLSERVER_ALLCOLUMNS_SQL = "select name from syscolumns where id={0}";
|
||||
|
||||
/*
|
||||
* 判断数据库类型
|
||||
*/
|
||||
|
||||
public static boolean dbTypeIsMySQL(String dbType) {
|
||||
return dbTypeIf(dbType, DATABSE_TYPE_MYSQL, DataBaseConstant.DB_TYPE_MYSQL_NUM) || dbTypeIf(dbType, DATABSE_TYPE_MARIADB, DataBaseConstant.DB_TYPE_MARIADB_NUM);
|
||||
}
|
||||
|
||||
public static boolean dbTypeIsOracle(String dbType) {
|
||||
return dbTypeIf(dbType, DATABSE_TYPE_ORACLE, DataBaseConstant.DB_TYPE_ORACLE_NUM);
|
||||
}
|
||||
|
||||
public static boolean dbTypeIsSQLServer(String dbType) {
|
||||
return dbTypeIf(dbType, DATABSE_TYPE_SQLSERVER, DataBaseConstant.DB_TYPE_SQLSERVER_NUM);
|
||||
}
|
||||
|
||||
public static boolean dbTypeIsPostgre(String dbType) {
|
||||
return dbTypeIf(dbType, DATABSE_TYPE_POSTGRE, DataBaseConstant.DB_TYPE_POSTGRESQL_NUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断数据库类型
|
||||
*/
|
||||
public static boolean dbTypeIf(String dbType, String... correctTypes) {
|
||||
for (String type : correctTypes) {
|
||||
if (type.equalsIgnoreCase(dbType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全 SQL
|
||||
* 拼接 where 条件
|
||||
*
|
||||
* @param sql
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public static String getFullSql(String sql, Map params) {
|
||||
return getFullSql(sql, params, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全 SQL
|
||||
* 拼接 where 条件
|
||||
* 拼接 order 排序
|
||||
*
|
||||
* @param sql
|
||||
* @param params
|
||||
* @param orderColumn 排序字段
|
||||
* @param orderBy 排序方式,只能是 DESC 或 ASC
|
||||
* @return
|
||||
*/
|
||||
public static String getFullSql(String sql, Map params, String orderColumn, String orderBy) {
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT t.* FROM ( ").append(sql).append(" ) t ");
|
||||
if (params != null && params.size() >= 1) {
|
||||
sqlBuilder.append("WHERE 1=1 ");
|
||||
for (Object key : params.keySet()) {
|
||||
String value = String.valueOf(params.get(key));
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
sqlBuilder.append(" AND (").append(key).append(" = N'").append(value).append("')");
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotBlank(orderColumn) && StringUtils.isNotBlank(orderBy)) {
|
||||
sqlBuilder.append("ORDER BY ").append(orderColumn).append(" ").append("DESC".equalsIgnoreCase(orderBy) ? "DESC" : "ASC");
|
||||
}
|
||||
}
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取求数量 SQL
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
public static String getCountSql(String sql) {
|
||||
return String.format("SELECT COUNT(1) \"total\" FROM ( %s ) temp_count", sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成分页查询 SQL
|
||||
*
|
||||
* @param dbType 数据库类型
|
||||
* @param sql
|
||||
* @param page
|
||||
* @param rows
|
||||
* @return
|
||||
*/
|
||||
public static String createPageSqlByDBType(String dbType, String sql, int page, int rows) {
|
||||
int beginNum = (page - 1) * rows;
|
||||
Object[] sqlParam = new Object[3];
|
||||
sqlParam[0] = sql;
|
||||
sqlParam[1] = String.valueOf(beginNum);
|
||||
sqlParam[2] = String.valueOf(rows);
|
||||
if (dbTypeIsMySQL(dbType)) {
|
||||
sql = MessageFormat.format(MYSQL_SQL, sqlParam);
|
||||
} else if (dbTypeIsPostgre(dbType)) {
|
||||
sql = MessageFormat.format(POSTGRE_SQL, sqlParam);
|
||||
} else {
|
||||
int beginIndex = (page - 1) * rows;
|
||||
int endIndex = beginIndex + rows;
|
||||
sqlParam[2] = Integer.toString(beginIndex);
|
||||
sqlParam[1] = Integer.toString(endIndex);
|
||||
if (dbTypeIsOracle(dbType)) {
|
||||
sql = MessageFormat.format(ORACLE_SQL, sqlParam);
|
||||
} else if (dbTypeIsSQLServer(dbType)) {
|
||||
sqlParam[0] = sql.substring(getAfterSelectInsertPoint(sql));
|
||||
sql = MessageFormat.format(SQLSERVER_SQL, sqlParam);
|
||||
}
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成分页查询 SQL
|
||||
*
|
||||
* @param sql
|
||||
* @param page
|
||||
* @param rows
|
||||
* @return
|
||||
*/
|
||||
public static String createPageSqlByDBKey(String dbKey, String sql, int page, int rows) {
|
||||
DynamicDataSourceModel dynamicSourceEntity = DataSourceCachePool.getCacheDynamicDataSourceModel(dbKey);
|
||||
String dbType = dynamicSourceEntity.getDbType();
|
||||
return createPageSqlByDBType(dbType, sql, page, rows);
|
||||
}
|
||||
|
||||
private static int getAfterSelectInsertPoint(String sql) {
|
||||
int selectIndex = sql.toLowerCase().indexOf("select");
|
||||
int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct");
|
||||
return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6);
|
||||
}
|
||||
|
||||
public static String getAllTableSql(String dbType, Object... params) {
|
||||
if (StringUtils.isNotEmpty(dbType)) {
|
||||
if (dbTypeIsMySQL(dbType)) {
|
||||
return MessageFormat.format(MYSQL_ALLTABLES_SQL, params);
|
||||
} else if (dbTypeIsOracle(dbType)) {
|
||||
return ORACLE__ALLTABLES_SQL;
|
||||
} else if (dbTypeIsPostgre(dbType)) {
|
||||
return POSTGRE__ALLTABLES_SQL;
|
||||
} else if (dbTypeIsSQLServer(dbType)) {
|
||||
return SQLSERVER__ALLTABLES_SQL;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getAllColumnSQL(String dbType, Object... params) {
|
||||
if (StringUtils.isNotEmpty(dbType)) {
|
||||
if (dbTypeIsMySQL(dbType)) {
|
||||
return MessageFormat.format(MYSQL_ALLCOLUMNS_SQL, params);
|
||||
} else if (dbTypeIsOracle(dbType)) {
|
||||
return MessageFormat.format(ORACLE_ALLCOLUMNS_SQL, params);
|
||||
} else if (dbTypeIsPostgre(dbType)) {
|
||||
return MessageFormat.format(POSTGRE_ALLCOLUMNS_SQL, params);
|
||||
} else if (dbTypeIsSQLServer(dbType)) {
|
||||
return MessageFormat.format(SQLSERVER_ALLCOLUMNS_SQL, params);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
package org.jeecg.common.util.filter;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @Description: TODO
|
||||
* @author: lsq
|
||||
* @date: 2021年08月09日 15:29
|
||||
*/
|
||||
public class FileTypeFilter {
|
||||
|
||||
//文件后缀
|
||||
private static String[] forbidType = {"jsp","php"};
|
||||
|
||||
// 初始化文件头类型,不够的自行补充
|
||||
final static HashMap<String, String> fileTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
fileTypeMap.put("3c25402070616765206c", "jsp");
|
||||
fileTypeMap.put("3c3f7068700a0a2f2a2a0a202a205048", "php");
|
||||
/* fileTypeMap.put("ffd8ffe000104a464946", "jpg");
|
||||
fileTypeMap.put("89504e470d0a1a0a0000", "png");
|
||||
fileTypeMap.put("47494638396126026f01", "gif");
|
||||
fileTypeMap.put("49492a00227105008037", "tif");
|
||||
fileTypeMap.put("424d228c010000000000", "bmp");
|
||||
fileTypeMap.put("424d8240090000000000", "bmp");
|
||||
fileTypeMap.put("424d8e1b030000000000", "bmp");
|
||||
fileTypeMap.put("41433130313500000000", "dwg");
|
||||
fileTypeMap.put("3c21444f435459504520", "html");
|
||||
fileTypeMap.put("3c21646f637479706520", "htm");
|
||||
fileTypeMap.put("48544d4c207b0d0a0942", "css");
|
||||
fileTypeMap.put("696b2e71623d696b2e71", "js");
|
||||
fileTypeMap.put("7b5c727466315c616e73", "rtf");
|
||||
fileTypeMap.put("38425053000100000000", "psd");
|
||||
fileTypeMap.put("46726f6d3a203d3f6762", "eml");
|
||||
fileTypeMap.put("d0cf11e0a1b11ae10000", "doc");
|
||||
fileTypeMap.put("5374616E64617264204A", "mdb");
|
||||
fileTypeMap.put("252150532D41646F6265", "ps");
|
||||
fileTypeMap.put("255044462d312e350d0a", "pdf");
|
||||
fileTypeMap.put("2e524d46000000120001", "rmvb");
|
||||
fileTypeMap.put("464c5601050000000900", "flv");
|
||||
fileTypeMap.put("00000020667479706d70", "mp4");
|
||||
fileTypeMap.put("49443303000000002176", "mp3");
|
||||
fileTypeMap.put("000001ba210001000180", "mpg");
|
||||
fileTypeMap.put("3026b2758e66cf11a6d9", "wmv");
|
||||
fileTypeMap.put("52494646e27807005741", "wav");
|
||||
fileTypeMap.put("52494646d07d60074156", "avi");
|
||||
fileTypeMap.put("4d546864000000060001", "mid");
|
||||
fileTypeMap.put("504b0304140000000800", "zip");
|
||||
fileTypeMap.put("526172211a0700cf9073", "rar");
|
||||
fileTypeMap.put("235468697320636f6e66", "ini");
|
||||
fileTypeMap.put("504b03040a0000000000", "jar");
|
||||
fileTypeMap.put("4d5a9000030000000400", "exe");
|
||||
fileTypeMap.put("3c25402070616765206c", "jsp");
|
||||
fileTypeMap.put("4d616e69666573742d56", "mf");
|
||||
fileTypeMap.put("3c3f786d6c2076657273", "xml");
|
||||
fileTypeMap.put("494e5345525420494e54", "sql");
|
||||
fileTypeMap.put("7061636b616765207765", "java");
|
||||
fileTypeMap.put("406563686f206f66660d", "bat");
|
||||
fileTypeMap.put("1f8b0800000000000000", "gz");
|
||||
fileTypeMap.put("6c6f67346a2e726f6f74", "properties");
|
||||
fileTypeMap.put("cafebabe0000002e0041", "class");
|
||||
fileTypeMap.put("49545346030000006000", "chm");
|
||||
fileTypeMap.put("04000000010000001300", "mxp");
|
||||
fileTypeMap.put("504b0304140006000800", "docx");
|
||||
fileTypeMap.put("6431303a637265617465", "torrent");
|
||||
fileTypeMap.put("6D6F6F76", "mov");
|
||||
fileTypeMap.put("FF575043", "wpd");
|
||||
fileTypeMap.put("CFAD12FEC5FD746F", "dbx");
|
||||
fileTypeMap.put("2142444E", "pst");
|
||||
fileTypeMap.put("AC9EBD8F", "qdf");
|
||||
fileTypeMap.put("E3828596", "pwl");
|
||||
fileTypeMap.put("2E7261FD", "ram");*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fileName
|
||||
* @return String
|
||||
* @description 通过文件后缀名获取文件类型
|
||||
*/
|
||||
private static String getFileTypeBySuffix(String fileName) {
|
||||
return fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件类型过滤
|
||||
*
|
||||
* @param file
|
||||
*/
|
||||
public static void fileTypeFilter(MultipartFile file) throws Exception {
|
||||
String suffix = getFileType(file);
|
||||
for (String type : forbidType) {
|
||||
if (type.contains(suffix)) {
|
||||
throw new Exception("上传失败,文件类型异常:" + suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过读取文件头部获得文件类型
|
||||
*
|
||||
* @param file
|
||||
* @return 文件类型
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
private static String getFileType(MultipartFile file) throws Exception {
|
||||
String fileExtendName = null;
|
||||
InputStream is;
|
||||
try {
|
||||
//is = new FileInputStream(file);
|
||||
is = file.getInputStream();
|
||||
byte[] b = new byte[10];
|
||||
is.read(b, 0, b.length);
|
||||
String fileTypeHex = String.valueOf(bytesToHexString(b));
|
||||
Iterator<String> keyIter = fileTypeMap.keySet().iterator();
|
||||
while (keyIter.hasNext()) {
|
||||
String key = keyIter.next();
|
||||
// 验证前5个字符比较
|
||||
if (key.toLowerCase().startsWith(fileTypeHex.toLowerCase().substring(0, 5))
|
||||
|| fileTypeHex.toLowerCase().substring(0, 5).startsWith(key.toLowerCase())) {
|
||||
fileExtendName = fileTypeMap.get(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 如果不是上述类型,则判断扩展名
|
||||
if (StringUtils.isBlank(fileExtendName)) {
|
||||
String fileName = file.getOriginalFilename();
|
||||
return getFileTypeBySuffix(fileName);
|
||||
}
|
||||
is.close();
|
||||
return fileExtendName;
|
||||
} catch (Exception exception) {
|
||||
throw new Exception(exception.getMessage(), exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得文件头部字符串
|
||||
*
|
||||
* @param src
|
||||
* @return
|
||||
*/
|
||||
private static String bytesToHexString(byte[] src) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if (src == null || src.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
int v = src[i] & 0xFF;
|
||||
String hv = Integer.toHexString(v);
|
||||
if (hv.length() < 2) {
|
||||
stringBuilder.append(0);
|
||||
}
|
||||
stringBuilder.append(hv);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.aliyun.oss.model.PutObjectResult;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.tomcat.util.http.fileupload.FileItemStream;
|
||||
import org.jeecg.common.util.CommonUtils;
|
||||
import org.jeecg.common.util.filter.FileTypeFilter;
|
||||
import org.jeecg.common.util.filter.StrAttackFilter;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -110,6 +111,9 @@ public class OssBootUtil {
|
|||
if("" == orgName){
|
||||
orgName=file.getName();
|
||||
}
|
||||
//update-begin-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
FileTypeFilter.fileTypeFilter(file);
|
||||
//update-end-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
orgName = CommonUtils.getFileName(orgName);
|
||||
String fileName = orgName.indexOf(".")==-1
|
||||
?orgName + "_" + System.currentTimeMillis()
|
||||
|
@ -136,6 +140,9 @@ public class OssBootUtil {
|
|||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return FILE_URL;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,8 @@ import cn.hutool.crypto.asymmetric.RSA;
|
|||
import cn.hutool.crypto.asymmetric.Sign;
|
||||
import cn.hutool.crypto.asymmetric.SignAlgorithm;
|
||||
import cn.hutool.crypto.symmetric.AES;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import org.jeecg.common.util.security.entity.*;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import javax.crypto.SecretKey;
|
||||
import java.security.KeyPair;
|
||||
|
||||
|
@ -34,7 +33,7 @@ public class SecurityTools {
|
|||
|
||||
String dencrptValue =aes.decryptStr(data);
|
||||
//log.info("解密后报文"+dencrptValue);
|
||||
resp.setData(new JSONObject(dencrptValue));
|
||||
resp.setData(JSONObject.parseObject(dencrptValue));
|
||||
|
||||
boolean verify = sign.verify(dencrptValue.getBytes(), Base64Decoder.decode(signData));
|
||||
resp.setSuccess(verify);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.jeecg.common.util.security.entity;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package org.jeecg.config;
|
||||
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.util.Utils;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.*;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
|
@ -10,8 +11,9 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.servlet.*;
|
||||
import java.io.IOException;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.util.Utils;
|
||||
|
||||
@Configuration
|
||||
@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
|
||||
|
@ -34,7 +36,7 @@ public class DruidConfig {
|
|||
* 去除Druid监控页面的广告
|
||||
*
|
||||
* @param properties DruidStatProperties属性集合
|
||||
* @return {@link org.springframework.boot.web.servlet.FilterRegistrationBean}
|
||||
* @return {@link FilterRegistrationBean}
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnWebApplication
|
||||
|
|
|
@ -20,6 +20,12 @@ public class StaticConfig {
|
|||
@Value(value = "${spring.mail.username}")
|
||||
private String emailFrom;
|
||||
|
||||
/**
|
||||
* 签名密钥串
|
||||
*/
|
||||
@Value(value = "${jeecg.signatureSecret}")
|
||||
private String signatureSecret;
|
||||
|
||||
|
||||
/*@Bean
|
||||
public void initStatic() {
|
||||
|
|
|
@ -110,7 +110,8 @@ public class Swagger2Config implements WebMvcConfigurer {
|
|||
// 描述
|
||||
.description("后台API接口")
|
||||
// 作者
|
||||
.contact("JEECG团队")
|
||||
.contact(new Contact("北京国炬信息技术有限公司","www.jeccg.com","jeecgos@163.com"))
|
||||
// .contact("JEECG团队")
|
||||
.license("The Apache License, Version 2.0")
|
||||
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
|
||||
.build();
|
||||
|
|
|
@ -1,130 +1,130 @@
|
|||
package org.jeecg.config.mybatis;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
|
||||
import net.sf.jsqlparser.expression.BinaryExpression;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.Parenthesis;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
|
||||
import net.sf.jsqlparser.expression.operators.relational.*;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.schema.Table;
|
||||
import net.sf.jsqlparser.statement.select.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 复写租户条件
|
||||
*/
|
||||
public class JeecgTenantParser extends TenantSqlParser {
|
||||
|
||||
/**
|
||||
* @param expression
|
||||
* @param table
|
||||
* @return
|
||||
*/
|
||||
protected Expression processTableAlias(Expression expression, Table table) {
|
||||
String tableAliasName;
|
||||
if (table.getAlias() == null) {
|
||||
tableAliasName = table.getName();
|
||||
} else {
|
||||
tableAliasName = table.getAlias().getName();
|
||||
}
|
||||
|
||||
// in
|
||||
if (expression instanceof InExpression) {
|
||||
InExpression in = (InExpression) expression;
|
||||
if (in.getLeftExpression() instanceof Column) {
|
||||
setTableAliasNameForColumn((Column) in.getLeftExpression(), tableAliasName);
|
||||
}
|
||||
|
||||
// 比较操作
|
||||
} else if (expression instanceof BinaryExpression) {
|
||||
BinaryExpression compare = (BinaryExpression) expression;
|
||||
if (compare.getLeftExpression() instanceof Column) {
|
||||
setTableAliasNameForColumn((Column) compare.getLeftExpression(), tableAliasName);
|
||||
} else if (compare.getRightExpression() instanceof Column) {
|
||||
setTableAliasNameForColumn((Column) compare.getRightExpression(), tableAliasName);
|
||||
}
|
||||
|
||||
// between
|
||||
} else if (expression instanceof Between) {
|
||||
Between between = (Between) expression;
|
||||
if (between.getLeftExpression() instanceof Column) {
|
||||
setTableAliasNameForColumn((Column) between.getLeftExpression(), tableAliasName);
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
private void setTableAliasNameForColumn(Column column, String tableAliasName) {
|
||||
column.setColumnName(tableAliasName + "." + column.getColumnName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认是按 tenant_id=1 按等于条件追加
|
||||
*
|
||||
* @param currentExpression 现有的条件:比如你原来的sql查询条件
|
||||
* @param table
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected Expression builderExpression(Expression currentExpression, Table table) {
|
||||
final Expression tenantExpression = this.getTenantHandler().getTenantId(true);
|
||||
Expression appendExpression;
|
||||
if (!(tenantExpression instanceof SupportsOldOracleJoinSyntax)) {
|
||||
appendExpression = new EqualsTo();
|
||||
((EqualsTo) appendExpression).setLeftExpression(this.getAliasColumn(table));
|
||||
((EqualsTo) appendExpression).setRightExpression(tenantExpression);
|
||||
} else {
|
||||
appendExpression = processTableAlias(tenantExpression, table);
|
||||
}
|
||||
if (currentExpression == null) {
|
||||
return appendExpression;
|
||||
}
|
||||
if (currentExpression instanceof BinaryExpression) {
|
||||
BinaryExpression binaryExpression = (BinaryExpression) currentExpression;
|
||||
if (binaryExpression.getLeftExpression() instanceof FromItem) {
|
||||
processFromItem((FromItem) binaryExpression.getLeftExpression());
|
||||
}
|
||||
if (binaryExpression.getRightExpression() instanceof FromItem) {
|
||||
processFromItem((FromItem) binaryExpression.getRightExpression());
|
||||
}
|
||||
} else if (currentExpression instanceof InExpression) {
|
||||
InExpression inExp = (InExpression) currentExpression;
|
||||
ItemsList rightItems = inExp.getRightItemsList();
|
||||
if (rightItems instanceof SubSelect) {
|
||||
processSelectBody(((SubSelect) rightItems).getSelectBody());
|
||||
}
|
||||
}
|
||||
if (currentExpression instanceof OrExpression) {
|
||||
return new AndExpression(new Parenthesis(currentExpression), appendExpression);
|
||||
} else {
|
||||
return new AndExpression(currentExpression, appendExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processPlainSelect(PlainSelect plainSelect, boolean addColumn) {
|
||||
FromItem fromItem = plainSelect.getFromItem();
|
||||
if (fromItem instanceof Table) {
|
||||
Table fromTable = (Table) fromItem;
|
||||
if (!this.getTenantHandler().doTableFilter(fromTable.getName())) {
|
||||
plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable));
|
||||
if (addColumn) {
|
||||
plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(this.getTenantHandler().getTenantIdColumn())));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
processFromItem(fromItem);
|
||||
}
|
||||
List<Join> joins = plainSelect.getJoins();
|
||||
if (joins != null && joins.size() > 0) {
|
||||
joins.forEach(j -> {
|
||||
processJoin(j);
|
||||
processFromItem(j.getRightItem());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//package org.jeecg.config.mybatis;
|
||||
//
|
||||
//import 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());
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
package org.jeecg.config.mybatis;
|
||||
|
||||
import com.baomidou.mybatisplus.core.parser.ISqlParser;
|
||||
import com.baomidou.mybatisplus.core.parser.ISqlParserFilter;
|
||||
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
|
||||
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.LongValue;
|
||||
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
||||
import net.sf.jsqlparser.expression.operators.relational.InExpression;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 单数据源配置(jeecg.datasource.open = false时生效)
|
||||
* @Author zhoujf
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@MapperScan(value={"org.jeecg.modules.**.mapper*"})
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
/**
|
||||
* tenant_id 字段名
|
||||
*/
|
||||
public static final String tenant_field = "tenant_id";
|
||||
|
||||
/**
|
||||
* 有哪些表需要做多租户 这些表需要添加一个字段 ,字段名和tenant_field对应的值一样
|
||||
*/
|
||||
private static final List<String> tenantTable = new ArrayList<String>();
|
||||
/**
|
||||
* ddl 关键字 判断不走多租户的sql过滤
|
||||
*/
|
||||
private static final List<String> DDL_KEYWORD = new ArrayList<String>();
|
||||
static {
|
||||
tenantTable.add("jee_bug_danbiao");
|
||||
DDL_KEYWORD.add("alter");
|
||||
}
|
||||
|
||||
/**
|
||||
* 多租户属于 SQL 解析部分,依赖 MP 分页插件
|
||||
*/
|
||||
@Bean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
PaginationInterceptor paginationInterceptor = new PaginationInterceptor().setLimit(-1);
|
||||
//多租户配置 配置后每次执行sql会走一遍他的转化器 如果不需要多租户功能 可以将其注释
|
||||
tenantConfig(paginationInterceptor);
|
||||
return paginationInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 多租户的配置
|
||||
* @param paginationInterceptor
|
||||
*/
|
||||
private void tenantConfig(PaginationInterceptor paginationInterceptor){
|
||||
/*
|
||||
* 【测试多租户】 SQL 解析处理拦截器<br>
|
||||
* 这里固定写成住户 1 实际情况你可以从cookie读取,因此数据看不到 【 麻花藤 】 这条记录( 注意观察 SQL )<br>
|
||||
*/
|
||||
List<ISqlParser> sqlParserList = new ArrayList<>();
|
||||
TenantSqlParser tenantSqlParser = new JeecgTenantParser();
|
||||
tenantSqlParser.setTenantHandler(new TenantHandler() {
|
||||
|
||||
@Override
|
||||
public Expression getTenantId(boolean select) {
|
||||
String tenant_id = oConvertUtils.getString(TenantContext.getTenant(),"0");
|
||||
return new LongValue(tenant_id);
|
||||
}
|
||||
@Override
|
||||
public String getTenantIdColumn() {
|
||||
return tenant_field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTableFilter(String tableName) {
|
||||
//true则不加租户条件查询 false则加
|
||||
// return excludeTable.contains(tableName);
|
||||
if(tenantTable.contains(tableName)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Expression in(String ids){
|
||||
final InExpression inExpression = new InExpression();
|
||||
inExpression.setLeftExpression(new Column(getTenantIdColumn()));
|
||||
final ExpressionList itemsList = new ExpressionList();
|
||||
final List<Expression> inValues = new ArrayList<>(2);
|
||||
for(String id:ids.split(",")){
|
||||
inValues.add(new LongValue(id));
|
||||
}
|
||||
itemsList.setExpressions(inValues);
|
||||
inExpression.setRightItemsList(itemsList);
|
||||
return inExpression;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
sqlParserList.add(tenantSqlParser);
|
||||
paginationInterceptor.setSqlParserList(sqlParserList);
|
||||
paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
|
||||
@Override
|
||||
public boolean doFilter(MetaObject metaObject) {
|
||||
String sql = (String) metaObject.getValue(PluginUtils.DELEGATE_BOUNDSQL_SQL);
|
||||
for(String tableName: tenantTable){
|
||||
String sql_lowercase = sql.toLowerCase();
|
||||
if(sql_lowercase.indexOf(tableName.toLowerCase())>=0){
|
||||
for(String key: DDL_KEYWORD){
|
||||
if(sql_lowercase.indexOf(key)>=0){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*if ("mapper路径.方法名".equals(ms.getId())) {
|
||||
//使用这种判断也可以避免走此过滤器
|
||||
return true;
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
// /**
|
||||
// * mybatis-plus SQL执行效率插件【生产环境可以关闭】
|
||||
// */
|
||||
// @Bean
|
||||
// public PerformanceInterceptor performanceInterceptor() {
|
||||
// return new PerformanceInterceptor();
|
||||
// }
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package org.jeecg.config.mybatis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.LongValue;
|
||||
|
||||
/**
|
||||
* 单数据源配置(jeecg.datasource.open = false时生效)
|
||||
* @Author zhoujf
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@MapperScan(value={"org.jeecg.modules.**.mapper*"})
|
||||
public class MybatisPlusSaasConfig {
|
||||
/**
|
||||
* tenant_id 字段名
|
||||
*/
|
||||
private static final String TENANT_FIELD_NAME = "tenant_id";
|
||||
/**
|
||||
* 哪些表需要做多租户 表需要添加一个字段 tenant_id
|
||||
*/
|
||||
private static final List<String> tenantTable = new ArrayList<String>();
|
||||
|
||||
static {
|
||||
tenantTable.add("demo");
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
// 先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
|
||||
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
|
||||
@Override
|
||||
public Expression getTenantId() {
|
||||
String tenant_id = oConvertUtils.getString(TenantContext.getTenant(),"0");
|
||||
return new LongValue(tenant_id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTenantIdColumn(){
|
||||
return TENANT_FIELD_NAME;
|
||||
}
|
||||
|
||||
// 返回 true 表示不走租户逻辑
|
||||
@Override
|
||||
public boolean ignoreTable(String tableName) {
|
||||
for(String temp: tenantTable){
|
||||
if(temp.equalsIgnoreCase(tableName)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 下个版本会删除,现在为了避免缓存出现问题不得不配置
|
||||
// * @return
|
||||
// */
|
||||
// @Bean
|
||||
// public ConfigurationCustomizer configurationCustomizer() {
|
||||
// return configuration -> configuration.setUseDeprecatedExecutor(false);
|
||||
// }
|
||||
// /**
|
||||
// * mybatis-plus SQL执行效率插件【生产环境可以关闭】
|
||||
// */
|
||||
// @Bean
|
||||
// public PerformanceInterceptor performanceInterceptor() {
|
||||
// return new PerformanceInterceptor();
|
||||
// }
|
||||
|
||||
}
|
|
@ -83,7 +83,6 @@ public class ShiroConfig {
|
|||
filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录
|
||||
filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在
|
||||
filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册
|
||||
filterChainDefinitionMap.put("/sys/user/querySysUser", "anon");//根据手机号获取用户信息
|
||||
filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号
|
||||
filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码
|
||||
filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
|
||||
|
@ -101,9 +100,11 @@ public class ShiroConfig {
|
|||
filterChainDefinitionMap.put("/**/*.png", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.ico", "anon");
|
||||
|
||||
// update-begin--Author:sunjianlei Date:20190813 for:排除字体格式的后缀
|
||||
filterChainDefinitionMap.put("/**/*.ttf", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.woff", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.woff2", "anon");
|
||||
// update-begin--Author:sunjianlei Date:20190813 for:排除字体格式的后缀
|
||||
|
||||
filterChainDefinitionMap.put("/druid/**", "anon");
|
||||
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
|
||||
|
@ -111,36 +112,26 @@ public class ShiroConfig {
|
|||
filterChainDefinitionMap.put("/webjars/**", "anon");
|
||||
filterChainDefinitionMap.put("/v2/**", "anon");
|
||||
|
||||
|
||||
// update-begin--Author:sunjianlei Date:20210510 for:排除消息通告查看详情页面(用于第三方APP)
|
||||
filterChainDefinitionMap.put("/sys/annountCement/show/**", "anon");
|
||||
// update-end--Author:sunjianlei Date:20210510 for:排除消息通告查看详情页面(用于第三方APP)
|
||||
|
||||
//积木报表排除
|
||||
filterChainDefinitionMap.put("/jmreport/**", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.js.map", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.css.map", "anon");
|
||||
//大屏设计器排除
|
||||
filterChainDefinitionMap.put("/bigscreen/**", "anon");
|
||||
|
||||
//测试示例
|
||||
filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); //大屏模板例子
|
||||
//filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试
|
||||
//filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面
|
||||
//filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试
|
||||
//大屏模板例子
|
||||
filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
|
||||
|
||||
//websocket排除
|
||||
filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告
|
||||
filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块
|
||||
filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
|
||||
|
||||
|
||||
//性能监控 TODO 存在安全漏洞泄露TOEKN(durid连接池也有)
|
||||
filterChainDefinitionMap.put("/actuator/**", "anon");
|
||||
|
||||
// 添加自己的过滤器并且取名为jwt
|
||||
Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
|
||||
//如果cloudServer为空 则说明是单体 需要加载跨域配置
|
||||
//如果cloudServer为空 则说明是单体 需要加载跨域配置【微服务跨域切换】
|
||||
Object cloudServer = env.getProperty(CommonConstant.CLOUD_SERVER_KEY);
|
||||
filterMap.put("jwt", new JwtFilter(cloudServer==null));
|
||||
shiroFilterFactoryBean.setFilters(filterMap);
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.jeecg.common.system.vo.LoginUser;
|
|||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.mybatis.TenantContext;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
@ -126,7 +127,17 @@ public class ShiroRealm extends AuthorizingRealm {
|
|||
if (!jwtTokenRefresh(token, username, loginUser.getPassword())) {
|
||||
throw new AuthenticationException("Token失效,请重新登录!");
|
||||
}
|
||||
|
||||
//update-begin-author:taoyan date:20210609 for:校验用户的tenant_id和前端传过来的是否一致
|
||||
String userTenantIds = loginUser.getRelTenantIds();
|
||||
if(oConvertUtils.isNotEmpty(userTenantIds)){
|
||||
String contextTenantId = TenantContext.getTenant();
|
||||
if(oConvertUtils.isNotEmpty(contextTenantId) && !"0".equals(contextTenantId)){
|
||||
if(String.join(",",userTenantIds).indexOf(contextTenantId)<0){
|
||||
throw new AuthenticationException("用户租户信息变更,请重新登陆!");
|
||||
}
|
||||
}
|
||||
}
|
||||
//update-end-author:taoyan date:20210609 for:校验用户的tenant_id和前端传过来的是否一致
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.mybatis.TenantContext;
|
||||
import org.jeecg.config.shiro.JwtToken;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
@ -22,6 +23,10 @@ import javax.servlet.http.HttpServletResponse;
|
|||
@Slf4j
|
||||
public class JwtFilter extends BasicHttpAuthenticationFilter {
|
||||
|
||||
/**
|
||||
* 默认开启跨域设置(使用单体)
|
||||
* 微服务情况下,此属性设置为false
|
||||
*/
|
||||
private boolean allowOrigin = true;
|
||||
|
||||
public JwtFilter(){}
|
||||
|
@ -55,7 +60,7 @@ public class JwtFilter extends BasicHttpAuthenticationFilter {
|
|||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||
String token = httpServletRequest.getHeader(CommonConstant.X_ACCESS_TOKEN);
|
||||
// update-begin--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数
|
||||
if(token == null){
|
||||
if (oConvertUtils.isEmpty(token)) {
|
||||
token = httpServletRequest.getParameter("token");
|
||||
}
|
||||
// update-end--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package org.jeecg.config.sign.interceptor;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.SortedMap;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
|
@ -11,10 +15,9 @@ import org.jeecg.config.sign.util.HttpUtils;
|
|||
import org.jeecg.config.sign.util.SignUtil;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.SortedMap;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 签名拦截器
|
||||
|
|
|
@ -11,8 +11,8 @@ import java.nio.charset.Charset;
|
|||
/**
|
||||
* 保存过滤器里面的流
|
||||
*
|
||||
* @author show
|
||||
* @date 10:03 2019/5/30
|
||||
* @author jeecg
|
||||
* @date 20210621
|
||||
*/
|
||||
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
package org.jeecg.config.sign.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -16,6 +10,14 @@ import java.util.Map;
|
|||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
/**
|
||||
* http 工具类 获取请求中的参数
|
||||
*
|
||||
|
|
|
@ -2,6 +2,10 @@ package org.jeecg.config.sign.util;
|
|||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.StaticConfig;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
@ -10,13 +14,11 @@ import java.util.SortedMap;
|
|||
/**
|
||||
* 签名工具类
|
||||
*
|
||||
* @author show
|
||||
* @date 10:01 2019/5/30
|
||||
* @author jeecg
|
||||
* @date 20210621
|
||||
*/
|
||||
@Slf4j
|
||||
public class SignUtil {
|
||||
//签名密钥串(前后端要一致,正式发布请自行修改)
|
||||
private static final String signatureSecret = "dd05f1c54d63749eda95f9fa6d49v442a";
|
||||
public static final String xPathVariable = "x-path-variable";
|
||||
|
||||
/**
|
||||
|
@ -44,6 +46,11 @@ public class SignUtil {
|
|||
params.remove("_t");
|
||||
String paramsJsonStr = JSONObject.toJSONString(params);
|
||||
log.info("Param paramsJsonStr : {}", paramsJsonStr);
|
||||
return DigestUtils.md5DigestAsHex((paramsJsonStr+signatureSecret).getBytes()).toUpperCase();
|
||||
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
|
||||
String signatureSecret = staticConfig.getSignatureSecret();
|
||||
if(oConvertUtils.isEmpty(signatureSecret) || signatureSecret.contains("${")){
|
||||
throw new JeecgBootException("签名密钥 ${jeecg.signatureSecret} 缺少配置 !!");
|
||||
}
|
||||
return DigestUtils.md5DigestAsHex((paramsJsonStr + signatureSecret).getBytes()).toUpperCase();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package org.jeecg.modules.base.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.SqlParser;
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.jeecg.common.api.dto.LogDTO;
|
||||
|
||||
|
@ -10,7 +10,8 @@ public interface BaseCommonMapper {
|
|||
* 保存日志
|
||||
* @param dto
|
||||
*/
|
||||
@SqlParser(filter=true)
|
||||
//@SqlParser(filter=true)
|
||||
@InterceptorIgnore
|
||||
void saveLog(@Param("dto")LogDTO dto);
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-base</artifactId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<description>公共模块</description>
|
||||
|
@ -29,7 +29,11 @@
|
|||
<!--加载hutool-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
</dependency>
|
||||
<!--加载beanutils-->
|
||||
<dependency>
|
||||
|
|
|
@ -8,9 +8,14 @@ package org.jeecg.common.constant;
|
|||
public interface CacheConstant {
|
||||
|
||||
/**
|
||||
* 字典信息缓存
|
||||
* 字典信息缓存(含禁用的字典项)
|
||||
*/
|
||||
public static final String SYS_DICT_CACHE = "sys:cache:dict";
|
||||
|
||||
/**
|
||||
* 字典信息缓存 status为有效的
|
||||
*/
|
||||
public static final String SYS_ENABLE_DICT_CACHE = "sys:cache:dictEnable";
|
||||
/**
|
||||
* 表字典信息缓存
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -75,4 +75,7 @@ public class JeecgDemo extends JeecgEntity implements Serializable {
|
|||
/** 个人简介 */
|
||||
@ApiModelProperty(value = "个人简介")
|
||||
private java.lang.String content;
|
||||
|
||||
@ApiModelProperty(value = "租户ID")
|
||||
private java.lang.Integer tenantId;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
|
||||
<!-- 查询用户已授权字段 -->
|
||||
<select id="queryUserAuth" resultType="java.lang.String">
|
||||
select perms from sys_user_role sur,
|
||||
select DISTINCT perms from sys_user_role sur,
|
||||
sys_role_permission srp,
|
||||
sys_permission sp
|
||||
where sur.role_id = srp.role_id
|
||||
and sp.id = srp.permission_id
|
||||
and user_id = #{userId}
|
||||
and sur.user_id = #{userId}
|
||||
and sp.perms like concat(concat('%',#{permsPrefix}),'%')
|
||||
</select>
|
||||
</mapper>
|
|
@ -10,6 +10,6 @@ WORKDIR /jeecg-boot
|
|||
|
||||
EXPOSE 8080
|
||||
|
||||
ADD ./target/jeecg-boot-module-system-2.4.5.jar ./
|
||||
ADD ./target/jeecg-boot-module-system-2.4.6.jar ./
|
||||
|
||||
CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jeecg-boot-module-system-2.4.5.jar
|
||||
CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jeecg-boot-module-system-2.4.6.jar
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
|||
<repository>
|
||||
<id>aliyun</id>
|
||||
<name>aliyun Repository</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
|
@ -22,7 +22,7 @@
|
|||
<repository>
|
||||
<id>jeecg</id>
|
||||
<name>jeecg Repository</name>
|
||||
<url>http://maven.jeecg.org/nexus/content/repositories/jeecg</url>
|
||||
<url>https://maven.jeecg.org/nexus/content/repositories/jeecg</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
|
@ -34,28 +34,35 @@
|
|||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-system-local-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework</groupId>
|
||||
<artifactId>jeewx-api</artifactId>
|
||||
<version>1.4.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- DEMO 示例模块 -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-module-demo</artifactId>
|
||||
<version>${jeecgboot.version}</version>
|
||||
<version>2.4.6</version>
|
||||
</dependency>
|
||||
<!-- jeewx api -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>spring-boot-starter-jimureport</artifactId>
|
||||
<version>1.3.4-beta</version>
|
||||
<groupId>org.jeecgframework</groupId>
|
||||
<artifactId>jeewx-api</artifactId>
|
||||
<version>1.4.5</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.jeecgframework</groupId>
|
||||
<artifactId>autopoi-web</artifactId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<groupId>commons-lang</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- 积木报表 -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>jimureport-spring-boot-starter</artifactId>
|
||||
<version>1.3.78</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
* @Description: 代码生成器,自定义DB配置
|
||||
* 【加了此类,则online模式DB连接,使用平台的配置,jeecg_database.properties配置无效;
|
||||
* 但是使用GUI模式代码生成,还是走jeecg_database.properties配置】
|
||||
* 提醒: 达梦数据库需要修改下面的参数${spring.datasource.dynamic.datasource.master.url:}配置
|
||||
* @author: scott
|
||||
* @date: 2021年02月18日 16:30
|
||||
*/
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package org.jeecg.modules.api.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.common.api.dto.message.*;
|
||||
import org.jeecg.common.api.dto.OnlineAuthDTO;
|
||||
import org.jeecg.common.api.dto.message.*;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.vo.*;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
|
@ -143,6 +143,17 @@ public class SystemAPIController {
|
|||
return sysBaseAPI.queryDictItemsByCode(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有效的数据字典
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryEnableDictItemsByCode")
|
||||
List<DictModel> queryEnableDictItemsByCode(@RequestParam("code") String code){
|
||||
return sysBaseAPI.queryEnableDictItemsByCode(code);
|
||||
}
|
||||
|
||||
|
||||
/** 查询所有的父级字典,按照create_time排序 */
|
||||
@GetMapping("/queryAllDict")
|
||||
List<DictModel> queryAllDict(){
|
||||
|
@ -158,17 +169,6 @@ public class SystemAPIController {
|
|||
return sysBaseAPI.queryAllDSysCategory();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表数据字典
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryTableDictItemsByCode")
|
||||
List<DictModel> queryTableDictItemsByCode(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code){
|
||||
return sysBaseAPI.queryTableDictItemsByCode(table, text, code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有部门 作为字典信息 id -->value,departName -->text
|
||||
|
@ -179,34 +179,6 @@ public class SystemAPIController {
|
|||
return sysBaseAPI.queryAllDepartBackDictModel();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询表字典 支持过滤数据
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param filterSql
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryFilterTableDictInfo")
|
||||
List<DictModel> queryFilterTableDictInfo(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("filterSql") String filterSql){
|
||||
return sysBaseAPI.queryFilterTableDictInfo(table, text, code, filterSql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定table的 text code 获取字典,包含text和value
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keyArray
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
@GetMapping("/queryTableDictByKeys")
|
||||
public List<String> queryTableDictByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keyArray") String[] keyArray){
|
||||
return sysBaseAPI.queryTableDictByKeys(table, text, code, keyArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有角色 带参
|
||||
* roleIds 默认选中角色
|
||||
|
@ -447,19 +419,6 @@ public class SystemAPIController {
|
|||
return sysBaseAPI.getCacheUser(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典表的 翻译
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/translateDictFromTable")
|
||||
public String translateDictFromTable(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("key") String key){
|
||||
return sysBaseAPI.translateDictFromTable(table, text, code, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通字典的翻译
|
||||
* @param code
|
||||
|
@ -477,18 +436,18 @@ public class SystemAPIController {
|
|||
* @param usernames
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryUsersByUsernames")
|
||||
List<JSONObject> queryUsersByUsernames(String usernames){
|
||||
@RequestMapping("/queryUsersByUsernames")
|
||||
List<JSONObject> queryUsersByUsernames(@RequestParam("usernames") String usernames){
|
||||
return this.sysBaseAPI.queryUsersByUsernames(usernames);
|
||||
}
|
||||
|
||||
/**
|
||||
* 37根据多个用户id(逗号分隔),查询返回多个用户信息
|
||||
* @param usernames
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryUsersByIds")
|
||||
List<JSONObject> queryUsersByIds(String ids){
|
||||
@RequestMapping("/queryUsersByIds")
|
||||
List<JSONObject> queryUsersByIds(@RequestParam("ids") String ids){
|
||||
return this.sysBaseAPI.queryUsersByIds(ids);
|
||||
}
|
||||
|
||||
|
@ -498,18 +457,18 @@ public class SystemAPIController {
|
|||
* @return
|
||||
*/
|
||||
@GetMapping("/queryDepartsByOrgcodes")
|
||||
List<JSONObject> queryDepartsByOrgcodes(String orgCodes){
|
||||
List<JSONObject> queryDepartsByOrgcodes(@RequestParam("orgCodes") String orgCodes){
|
||||
return this.sysBaseAPI.queryDepartsByOrgcodes(orgCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 39根据多个部门ID(逗号分隔),查询返回多个部门信息
|
||||
* @param orgCodes
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryDepartsByIds")
|
||||
List<JSONObject> queryDepartsByIds(String orgCodes){
|
||||
return this.sysBaseAPI.queryDepartsByIds(orgCodes);
|
||||
List<JSONObject> queryDepartsByIds(@RequestParam("ids") String ids){
|
||||
return this.sysBaseAPI.queryDepartsByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -530,4 +489,146 @@ public class SystemAPIController {
|
|||
List<Map> getDeptUserByOrgCode(@RequestParam("orgCode")String orgCode){
|
||||
return this.sysBaseAPI.getDeptUserByOrgCode(orgCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分类字典翻译
|
||||
*
|
||||
* @param ids 分类字典表id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/loadCategoryDictItem")
|
||||
public List<String> loadCategoryDictItem(@RequestParam("ids") String ids) {
|
||||
return sysBaseAPI.loadCategoryDictItem(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典code加载字典text
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param keys 要查询的key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/loadDictItem")
|
||||
public List<String> loadDictItem(@RequestParam("dictCode") String dictCode, @RequestParam("keys") String keys) {
|
||||
return sysBaseAPI.loadDictItem(dictCode, keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典code查询字典项
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param dictCode 要查询的key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getDictItems")
|
||||
public List<DictModel> getDictItems(@RequestParam("dictCode") String dictCode) {
|
||||
return sysBaseAPI.getDictItems(dictCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据多个字典code查询多个字典项
|
||||
*
|
||||
* @param dictCodeList
|
||||
* @return key = dictCode ; value=对应的字典项
|
||||
*/
|
||||
@RequestMapping("/getManyDictItems")
|
||||
public Map<String, List<DictModel>> getManyDictItems(@RequestParam("dictCodeList") List<String> dictCodeList) {
|
||||
return sysBaseAPI.getManyDictItems(dictCodeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【下拉搜索】
|
||||
* 大数据量的字典表 走异步加载,即前端输入内容过滤数据
|
||||
*
|
||||
* @param dictCode 字典code格式:table,text,code
|
||||
* @param keyword 过滤关键字
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/loadDictItemByKeyword")
|
||||
public List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize) {
|
||||
return sysBaseAPI.loadDictItemByKeyword(dictCode, keyword, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 48 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割
|
||||
* @param dictCodes
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/translateManyDict")
|
||||
public Map<String, List<DictModel>> translateManyDict(@RequestParam("dictCodes") String dictCodes, @RequestParam("keys") String keys){
|
||||
return this.sysBaseAPI.translateManyDict(dictCodes, keys);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取表数据字典 【接口签名验证】
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryTableDictItemsByCode")
|
||||
List<DictModel> queryTableDictItemsByCode(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code){
|
||||
return sysBaseAPI.queryTableDictItemsByCode(table, text, code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询表字典 支持过滤数据 【接口签名验证】
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param filterSql
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryFilterTableDictInfo")
|
||||
List<DictModel> queryFilterTableDictInfo(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("filterSql") String filterSql){
|
||||
return sysBaseAPI.queryFilterTableDictInfo(table, text, code, filterSql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【接口签名验证】
|
||||
* 查询指定table的 text code 获取字典,包含text和value
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keyArray
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
@GetMapping("/queryTableDictByKeys")
|
||||
public List<String> queryTableDictByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keyArray") String[] keyArray){
|
||||
return sysBaseAPI.queryTableDictByKeys(table, text, code, keyArray);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 字典表的 翻译【接口签名验证】
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/translateDictFromTable")
|
||||
public String translateDictFromTable(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("key") String key){
|
||||
return sysBaseAPI.translateDictFromTable(table, text, code, key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 【接口签名验证】
|
||||
* 49 字典表的 翻译,可批量
|
||||
*
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys 多个用逗号分割
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/translateDictFromTableByKeys")
|
||||
public List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys) {
|
||||
return this.sysBaseAPI.translateDictFromTableByKeys(table, text, code, keys);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.jeecg.modules.quartz.service.IQuartzJobService;
|
|||
import org.quartz.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -43,6 +44,7 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
|
|||
* 保存&启动定时任务
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = JeecgBootException.class)
|
||||
public boolean saveAndScheduleJob(QuartzJob quartzJob) {
|
||||
// DB设置修改
|
||||
quartzJob.setDelFlag(CommonConstant.DEL_FLAG_0);
|
||||
|
@ -60,6 +62,7 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
|
|||
* 恢复定时任务
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = JeecgBootException.class)
|
||||
public boolean resumeJob(QuartzJob quartzJob) {
|
||||
schedulerDelete(quartzJob.getId());
|
||||
schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
|
||||
|
@ -72,6 +75,7 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
|
|||
* @throws SchedulerException
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = JeecgBootException.class)
|
||||
public boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException {
|
||||
if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
|
||||
schedulerDelete(quartzJob.getId());
|
||||
|
@ -86,6 +90,7 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
|
|||
* 删除&停止删除定时任务
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = JeecgBootException.class)
|
||||
public boolean deleteAndStopJob(QuartzJob job) {
|
||||
schedulerDelete(job.getId());
|
||||
boolean ok = this.removeById(job.getId());
|
||||
|
@ -116,6 +121,7 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = JeecgBootException.class)
|
||||
public void pause(QuartzJob quartzJob){
|
||||
schedulerDelete(quartzJob.getId());
|
||||
quartzJob.setStatus(CommonConstant.STATUS_DISABLE);
|
||||
|
|
|
@ -211,7 +211,7 @@ public class CommonController {
|
|||
InputStream inputStream = null;
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
imgPath = imgPath.replace("..", "");
|
||||
imgPath = imgPath.replace("..", "").replace("../","");
|
||||
if (imgPath.endsWith(",")) {
|
||||
imgPath = imgPath.substring(0, imgPath.length() - 1);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyuncs.exceptions.ClientException;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
|
@ -13,18 +12,16 @@ import org.jeecg.common.api.vo.Result;
|
|||
import org.jeecg.common.constant.CacheConstant;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.*;
|
||||
import org.jeecg.common.util.encryption.EncryptedString;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.system.entity.SysDepart;
|
||||
import org.jeecg.modules.system.entity.SysTenant;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.model.SysLoginModel;
|
||||
import org.jeecg.modules.system.service.ISysDepartService;
|
||||
import org.jeecg.modules.system.service.ISysDictService;
|
||||
import org.jeecg.modules.system.service.ISysLogService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.jeecg.modules.system.service.*;
|
||||
import org.jeecg.modules.system.util.RandImageUtil;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -55,6 +52,8 @@ public class LoginController {
|
|||
@Autowired
|
||||
private ISysDepartService sysDepartService;
|
||||
@Autowired
|
||||
private ISysTenantService sysTenantService;
|
||||
@Autowired
|
||||
private ISysDictService sysDictService;
|
||||
@Resource
|
||||
private BaseCommonService baseCommonService;
|
||||
|
@ -357,12 +356,6 @@ public class LoginController {
|
|||
private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
|
||||
String syspassword = sysUser.getPassword();
|
||||
String username = sysUser.getUsername();
|
||||
// 生成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);
|
||||
|
||||
// 获取用户部门信息
|
||||
JSONObject obj = new JSONObject();
|
||||
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
|
||||
|
@ -382,6 +375,25 @@ public class LoginController {
|
|||
// update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
|
||||
obj.put("multi_depart", 2);
|
||||
}
|
||||
// update-begin--Author:sunjianlei Date:20210802 for:获取用户租户信息
|
||||
String tenantIds = sysUser.getRelTenantIds();
|
||||
if (oConvertUtils.isNotEmpty(tenantIds)) {
|
||||
List<String> tenantIdList = Arrays.asList(tenantIds.split(","));
|
||||
// 该方法仅查询有效的租户,如果返回0个就说明所有的租户均无效。
|
||||
List<SysTenant> tenantList = sysTenantService.queryEffectiveTenant(tenantIdList);
|
||||
if (tenantList.size() == 0) {
|
||||
result.error500("与该用户关联的租户均已被冻结,无法登录!");
|
||||
return result;
|
||||
} else {
|
||||
obj.put("tenantList", tenantList);
|
||||
}
|
||||
}
|
||||
// update-end--Author:sunjianlei Date:20210802 for:获取用户租户信息
|
||||
// 生成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);
|
||||
obj.put("userInfo", sysUser);
|
||||
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.jeecg.modules.system.service.ISysAnnouncementSendService;
|
|||
import org.jeecg.modules.system.service.ISysAnnouncementService;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppWechatEnterpriseServiceImpl;
|
||||
import org.jeecg.modules.system.util.XSSUtils;
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
|
@ -119,6 +120,10 @@ public class SysAnnouncementController {
|
|||
public Result<SysAnnouncement> add(@RequestBody SysAnnouncement sysAnnouncement) {
|
||||
Result<SysAnnouncement> result = new Result<SysAnnouncement>();
|
||||
try {
|
||||
// update-begin-author:liusq date:20210804 for:标题处理xss攻击的问题
|
||||
String title = XSSUtils.striptXSS(sysAnnouncement.getTitile());
|
||||
sysAnnouncement.setTitile(title);
|
||||
// update-end-author:liusq date:20210804 for:标题处理xss攻击的问题
|
||||
sysAnnouncement.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
|
||||
sysAnnouncement.setSendStatus(CommonSendStatus.UNPUBLISHED_STATUS_0);//未发布
|
||||
sysAnnouncementService.saveAnnouncement(sysAnnouncement);
|
||||
|
@ -142,6 +147,10 @@ public class SysAnnouncementController {
|
|||
if(sysAnnouncementEntity==null) {
|
||||
result.error500("未找到对应实体");
|
||||
}else {
|
||||
// update-begin-author:liusq date:20210804 for:标题处理xss攻击的问题
|
||||
String title = XSSUtils.striptXSS(sysAnnouncement.getTitile());
|
||||
sysAnnouncement.setTitile(title);
|
||||
// update-end-author:liusq date:20210804 for:标题处理xss攻击的问题
|
||||
boolean ok = sysAnnouncementService.upDateAnnouncement(sysAnnouncement);
|
||||
//TODO 返回false说明什么?
|
||||
if(ok) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
|
@ -71,8 +72,13 @@ public class SysDepartController {
|
|||
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
try {
|
||||
if(oConvertUtils.isNotEmpty(user.getUserIdentity()) && user.getUserIdentity().equals( CommonConstant.USER_IDENTITY_2 )){
|
||||
List<SysDepartTreeModel> list = sysDepartService.queryMyDeptTreeList(user.getDepartIds());
|
||||
//update-begin--Author:liusq Date:20210624 for:部门查询ids为空后的前端显示问题 issues/I3UD06
|
||||
String departIds = user.getDepartIds();
|
||||
if(StringUtils.isNotBlank(departIds)){
|
||||
List<SysDepartTreeModel> list = sysDepartService.queryMyDeptTreeList(departIds);
|
||||
result.setResult(list);
|
||||
}
|
||||
//update-end--Author:liusq Date:20210624 for:部门查询ids为空后的前端显示问题 issues/I3UD06
|
||||
result.setMessage(CommonConstant.USER_IDENTITY_2.toString());
|
||||
result.setSuccess(true);
|
||||
}else{
|
||||
|
|
|
@ -111,33 +111,6 @@ public class SysDictController {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典数据
|
||||
* @param dictCode 字典code
|
||||
* @param dictCode 表名,文本字段,code字段 | 举例:sys_user,realname,id
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getDictItems/{dictCode}", method = RequestMethod.GET)
|
||||
public Result<List<DictModel>> getDictItems(@PathVariable String dictCode, @RequestParam(value = "sign",required = false) String sign,HttpServletRequest request) {
|
||||
log.info(" dictCode : "+ dictCode);
|
||||
Result<List<DictModel>> result = new Result<List<DictModel>>();
|
||||
try {
|
||||
List<DictModel> ls = sysDictService.getDictItems(dictCode);
|
||||
if (ls == null) {
|
||||
result.error500("字典Code格式不正确!");
|
||||
return result;
|
||||
}
|
||||
result.setSuccess(true);
|
||||
result.setResult(ls);
|
||||
log.debug(result.toString());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
result.error500("操作失败");
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部字典数据
|
||||
*
|
||||
|
@ -172,7 +145,36 @@ public class SysDictController {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取字典数据 【接口签名验证】
|
||||
* @param dictCode 字典code
|
||||
* @param dictCode 表名,文本字段,code字段 | 举例:sys_user,realname,id
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getDictItems/{dictCode}", method = RequestMethod.GET)
|
||||
public Result<List<DictModel>> getDictItems(@PathVariable String dictCode, @RequestParam(value = "sign",required = false) String sign,HttpServletRequest request) {
|
||||
log.info(" dictCode : "+ dictCode);
|
||||
Result<List<DictModel>> result = new Result<List<DictModel>>();
|
||||
try {
|
||||
List<DictModel> ls = sysDictService.getDictItems(dictCode);
|
||||
if (ls == null) {
|
||||
result.error500("字典Code格式不正确!");
|
||||
return result;
|
||||
}
|
||||
result.setSuccess(true);
|
||||
result.setResult(ls);
|
||||
log.debug(result.toString());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
result.error500("操作失败");
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 【接口签名验证】
|
||||
* 【JSearchSelectTag下拉搜索组件专用接口】
|
||||
* 大数据量的字典表 走异步加载 即前端输入内容过滤数据
|
||||
* @param dictCode 字典code格式:table,text,code
|
||||
|
@ -203,6 +205,7 @@ public class SysDictController {
|
|||
}
|
||||
|
||||
/**
|
||||
* 【接口签名验证】
|
||||
* 【给表单设计器的表字典使用】下拉搜索模式,有值时动态拼接数据
|
||||
* @param dictCode
|
||||
* @param keyword 当前控件的值,可以逗号分割
|
||||
|
@ -243,7 +246,7 @@ public class SysDictController {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 【接口签名验证】
|
||||
* 根据字典code加载字典text 返回
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param keys 要查询的key
|
||||
|
@ -280,6 +283,7 @@ public class SysDictController {
|
|||
}
|
||||
|
||||
/**
|
||||
* 【接口签名验证】
|
||||
* 根据表名——显示字段-存储字段 pid 加载树形数据
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -378,7 +382,7 @@ public class SysDictController {
|
|||
*/
|
||||
//@RequiresRoles({"admin"})
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
|
||||
@CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true)
|
||||
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
|
||||
public Result<SysDict> delete(@RequestParam(name="id",required=true) String id) {
|
||||
Result<SysDict> result = new Result<SysDict>();
|
||||
boolean ok = sysDictService.removeById(id);
|
||||
|
@ -397,7 +401,7 @@ public class SysDictController {
|
|||
*/
|
||||
//@RequiresRoles({"admin"})
|
||||
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
|
||||
@CacheEvict(value= CacheConstant.SYS_DICT_CACHE, allEntries=true)
|
||||
@CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
|
||||
public Result<SysDict> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
Result<SysDict> result = new Result<SysDict>();
|
||||
if(oConvertUtils.isEmpty(ids)) {
|
||||
|
@ -418,6 +422,7 @@ public class SysDictController {
|
|||
Result<?> result = new Result<SysDict>();
|
||||
//清空字典缓存
|
||||
Set keys = redisTemplate.keys(CacheConstant.SYS_DICT_CACHE + "*");
|
||||
Set keys7 = redisTemplate.keys(CacheConstant.SYS_ENABLE_DICT_CACHE + "*");
|
||||
Set keys2 = redisTemplate.keys(CacheConstant.SYS_DICT_TABLE_CACHE + "*");
|
||||
Set keys21 = redisTemplate.keys(CacheConstant.SYS_DICT_TABLE_BY_KEYS_CACHE + "*");
|
||||
Set keys3 = redisTemplate.keys(CacheConstant.SYS_DEPARTS_CACHE + "*");
|
||||
|
@ -431,6 +436,7 @@ public class SysDictController {
|
|||
redisTemplate.delete(keys4);
|
||||
redisTemplate.delete(keys5);
|
||||
redisTemplate.delete(keys6);
|
||||
redisTemplate.delete(keys7);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -562,7 +568,7 @@ public class SysDictController {
|
|||
}
|
||||
|
||||
/**
|
||||
* 取回
|
||||
* 逻辑删除的字段,进行取回
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
|
|
|
@ -73,7 +73,7 @@ public class SysDictItemController {
|
|||
*/
|
||||
//@RequiresRoles({"admin"})
|
||||
@RequestMapping(value = "/add", method = RequestMethod.POST)
|
||||
@CacheEvict(value= CacheConstant.SYS_DICT_CACHE, allEntries=true)
|
||||
@CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
|
||||
public Result<SysDictItem> add(@RequestBody SysDictItem sysDictItem) {
|
||||
Result<SysDictItem> result = new Result<SysDictItem>();
|
||||
try {
|
||||
|
@ -94,7 +94,7 @@ public class SysDictItemController {
|
|||
*/
|
||||
//@RequiresRoles({"admin"})
|
||||
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
|
||||
@CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true)
|
||||
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
|
||||
public Result<SysDictItem> edit(@RequestBody SysDictItem sysDictItem) {
|
||||
Result<SysDictItem> result = new Result<SysDictItem>();
|
||||
SysDictItem sysdict = sysDictItemService.getById(sysDictItem.getId());
|
||||
|
@ -118,7 +118,7 @@ public class SysDictItemController {
|
|||
*/
|
||||
//@RequiresRoles({"admin"})
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
|
||||
@CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true)
|
||||
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
|
||||
public Result<SysDictItem> delete(@RequestParam(name="id",required=true) String id) {
|
||||
Result<SysDictItem> result = new Result<SysDictItem>();
|
||||
SysDictItem joinSystem = sysDictItemService.getById(id);
|
||||
|
@ -140,7 +140,7 @@ public class SysDictItemController {
|
|||
*/
|
||||
//@RequiresRoles({"admin"})
|
||||
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
|
||||
@CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true)
|
||||
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
|
||||
public Result<SysDictItem> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
Result<SysDictItem> result = new Result<SysDictItem>();
|
||||
if(ids==null || "".equals(ids.trim())) {
|
||||
|
|
|
@ -5,11 +5,11 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.constant.enums.RoleIndexConfigEnum;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.MD5Util;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
|
@ -52,6 +52,9 @@ public class SysPermissionController {
|
|||
@Autowired
|
||||
private ISysDepartPermissionService sysDepartPermissionService;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService sysUserService;
|
||||
|
||||
/**
|
||||
* 加载数据节点
|
||||
*
|
||||
|
@ -212,6 +215,18 @@ public class SysPermissionController {
|
|||
//update-begin-author:taoyan date:20200211 for: TASK #3368 【路由缓存】首页的缓存设置有问题,需要根据后台的路由配置来实现是否缓存
|
||||
if(!PermissionDataUtil.hasIndexPage(metaList)){
|
||||
SysPermission indexMenu = sysPermissionService.list(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getName,"首页")).get(0);
|
||||
//update-begin--Author:liusq Date:20210624 for:自定义首页地址LOWCOD-1578
|
||||
List<String> roles = sysUserService.getRole(loginUser.getUsername());
|
||||
if(roles.size()>0){
|
||||
for (String code:roles) {
|
||||
String componentUrl = RoleIndexConfigEnum.getIndexByCode(code);
|
||||
if(StringUtils.isNotBlank(componentUrl)){
|
||||
indexMenu.setComponent(componentUrl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//update-end--Author:liusq Date:20210624 for:自定义首页地址LOWCOD-1578
|
||||
metaList.add(0,indexMenu);
|
||||
}
|
||||
//update-end-author:taoyan date:20200211 for: TASK #3368 【路由缓存】首页的缓存设置有问题,需要根据后台的路由配置来实现是否缓存
|
||||
|
|
|
@ -14,9 +14,9 @@ import org.jeecg.modules.system.entity.SysTenant;
|
|||
import org.jeecg.modules.system.service.ISysTenantService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -99,7 +99,7 @@ public class SysTenantController {
|
|||
*/
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
|
||||
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
|
||||
sysTenantService.removeById(id);
|
||||
sysTenantService.removeTenantById(id);
|
||||
return Result.ok("删除成功");
|
||||
}
|
||||
|
||||
|
@ -114,9 +114,25 @@ public class SysTenantController {
|
|||
if(oConvertUtils.isEmpty(ids)) {
|
||||
result.error500("未选中租户!");
|
||||
}else {
|
||||
List<String> ls = Arrays.asList(ids.split(","));
|
||||
sysTenantService.removeByIds(ls);
|
||||
result.success("删除成功!");
|
||||
String[] ls = ids.split(",");
|
||||
// 过滤掉已被引用的租户
|
||||
List<String> idList = new ArrayList<>();
|
||||
for (String id : ls) {
|
||||
int userCount = sysTenantService.countUserLinkTenant(id);
|
||||
if (userCount == 0) {
|
||||
idList.add(id);
|
||||
}
|
||||
}
|
||||
if (idList.size() > 0) {
|
||||
sysTenantService.removeByIds(idList);
|
||||
if (ls.length == idList.size()) {
|
||||
result.success("删除成功!");
|
||||
} else {
|
||||
result.success("部分删除成功!(被引用的租户无法删除)");
|
||||
}
|
||||
}else {
|
||||
result.error500("选择的租户都已被引用,无法删除!");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -942,41 +942,41 @@ public class SysUserController {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户名或手机号查询用户信息
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/querySysUser")
|
||||
public Result<Map<String, Object>> querySysUser(SysUser sysUser) {
|
||||
String phone = sysUser.getPhone();
|
||||
String username = sysUser.getUsername();
|
||||
Result<Map<String, Object>> result = new Result<Map<String, Object>>();
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
if (oConvertUtils.isNotEmpty(phone)) {
|
||||
SysUser user = sysUserService.getUserByPhone(phone);
|
||||
if(user!=null) {
|
||||
map.put("username",user.getUsername());
|
||||
map.put("phone",user.getPhone());
|
||||
result.setSuccess(true);
|
||||
result.setResult(map);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (oConvertUtils.isNotEmpty(username)) {
|
||||
SysUser user = sysUserService.getUserByName(username);
|
||||
if(user!=null) {
|
||||
map.put("username",user.getUsername());
|
||||
map.put("phone",user.getPhone());
|
||||
result.setSuccess(true);
|
||||
result.setResult(map);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result.setSuccess(false);
|
||||
result.setMessage("验证失败");
|
||||
return result;
|
||||
}
|
||||
// /**
|
||||
// * 根据用户名或手机号查询用户信息
|
||||
// * @param
|
||||
// * @return
|
||||
// */
|
||||
// @GetMapping("/querySysUser")
|
||||
// public Result<Map<String, Object>> querySysUser(SysUser sysUser) {
|
||||
// String phone = sysUser.getPhone();
|
||||
// String username = sysUser.getUsername();
|
||||
// Result<Map<String, Object>> result = new Result<Map<String, Object>>();
|
||||
// Map<String, Object> map = new HashMap<String, Object>();
|
||||
// if (oConvertUtils.isNotEmpty(phone)) {
|
||||
// SysUser user = sysUserService.getUserByPhone(phone);
|
||||
// if(user!=null) {
|
||||
// map.put("username",user.getUsername());
|
||||
// map.put("phone",user.getPhone());
|
||||
// result.setSuccess(true);
|
||||
// result.setResult(map);
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
// if (oConvertUtils.isNotEmpty(username)) {
|
||||
// SysUser user = sysUserService.getUserByName(username);
|
||||
// if(user!=null) {
|
||||
// map.put("username",user.getUsername());
|
||||
// map.put("phone",user.getPhone());
|
||||
// result.setSuccess(true);
|
||||
// result.setResult(map);
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
// result.setSuccess(false);
|
||||
// result.setMessage("验证失败");
|
||||
// return result;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 用户手机号验证
|
||||
|
@ -1028,7 +1028,7 @@ public class SysUserController {
|
|||
result.setSuccess(false);
|
||||
return result;
|
||||
}
|
||||
if(!smscode.equals(object)) {
|
||||
if(!smscode.equals(object.toString())) {
|
||||
result.setMessage("短信验证码不匹配!");
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
|
@ -1347,7 +1347,7 @@ public class SysUserController {
|
|||
result.setSuccess(false);
|
||||
return result;
|
||||
}
|
||||
if(!smscode.equals(object)) {
|
||||
if(!smscode.equals(object.toString())) {
|
||||
result.setMessage("短信验证码不匹配!");
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
|
@ -1362,4 +1362,20 @@ public class SysUserController {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据对象里面的属性值作in查询 属性可能会变 用户组件用到
|
||||
* @param sysUser
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getMultiUser")
|
||||
public List<SysUser> getMultiUser(SysUser sysUser){
|
||||
QueryWrapper<SysUser> queryWrapper = QueryGenerator.initQueryWrapper(sysUser, null);
|
||||
List<SysUser> ls = this.sysUserService.list(queryWrapper);
|
||||
for(SysUser user: ls){
|
||||
user.setPassword(null);
|
||||
user.setSalt(null);
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
|
@ -14,17 +18,15 @@ import org.jeecg.common.util.RedisUtil;
|
|||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.jeecg.modules.system.vo.SysOnlineVO;
|
||||
import org.jeecg.modules.system.vo.SysUserOnlineVO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @Description: 在线用户
|
||||
|
@ -35,7 +37,7 @@ import java.util.List;
|
|||
@RestController
|
||||
@RequestMapping("/sys/online")
|
||||
@Slf4j
|
||||
public class SysOnlineController {
|
||||
public class SysUserOnlineController {
|
||||
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
@ -53,13 +55,13 @@ public class SysOnlineController {
|
|||
private BaseCommonService baseCommonService;
|
||||
|
||||
@RequestMapping(value = "/list", method = RequestMethod.GET)
|
||||
public Result<Page<SysOnlineVO>> list(@RequestParam(name="username", required=false) String username, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
public Result<Page<SysUserOnlineVO>> list(@RequestParam(name="username", required=false) String username, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
|
||||
Collection<String> keys = redisTemplate.keys(CommonConstant.PREFIX_USER_TOKEN + "*");
|
||||
SysOnlineVO online;
|
||||
List<SysOnlineVO> onlineList = new ArrayList<SysOnlineVO>();
|
||||
SysUserOnlineVO online;
|
||||
List<SysUserOnlineVO> onlineList = new ArrayList<SysUserOnlineVO>();
|
||||
for (String key : keys) {
|
||||
online = new SysOnlineVO();
|
||||
online = new SysUserOnlineVO();
|
||||
String token = (String) redisUtil.get(key);
|
||||
if (!StringUtils.isEmpty(token)){
|
||||
online.setToken(token);
|
||||
|
@ -75,9 +77,9 @@ public class SysOnlineController {
|
|||
}
|
||||
}
|
||||
|
||||
Page<SysOnlineVO> page = new Page<SysOnlineVO>(pageNo, pageSize);
|
||||
Page<SysUserOnlineVO> page = new Page<SysUserOnlineVO>(pageNo, pageSize);
|
||||
int count = onlineList.size();
|
||||
List<SysOnlineVO> pages = new ArrayList<>();
|
||||
List<SysUserOnlineVO> pages = new ArrayList<>();
|
||||
//计算当前页第一条数据的下标
|
||||
int currId = pageNo>1 ? (pageNo-1)*pageSize:0;
|
||||
for (int i=0; i<pageSize && i<count - currId;i++){
|
||||
|
@ -92,7 +94,7 @@ public class SysOnlineController {
|
|||
|
||||
Collections.reverse(onlineList);
|
||||
onlineList.removeAll(Collections.singleton(null));
|
||||
Result<Page<SysOnlineVO>> result = new Result<Page<SysOnlineVO>>();
|
||||
Result<Page<SysUserOnlineVO>> result = new Result<Page<SysUserOnlineVO>>();
|
||||
result.setSuccess(true);
|
||||
result.setResult(page);
|
||||
return result;
|
||||
|
@ -102,7 +104,7 @@ public class SysOnlineController {
|
|||
* 强退用户
|
||||
*/
|
||||
@RequestMapping(value = "/forceLogout",method = RequestMethod.POST)
|
||||
public Result<Object> forceLogout(@RequestBody SysOnlineVO online) {
|
||||
public Result<Object> forceLogout(@RequestBody SysUserOnlineVO online) {
|
||||
//用户退出逻辑
|
||||
if(oConvertUtils.isEmpty(online.getToken())) {
|
||||
return Result.error("退出登录失败!");
|
|
@ -1,6 +1,5 @@
|
|||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.xkcoding.justauth.AuthRequestFactory;
|
||||
|
@ -11,18 +10,22 @@ import me.zhyd.oauth.model.AuthResponse;
|
|||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CacheConstant;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.*;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.PasswordUtil;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.RestUtil;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.thirdapp.ThirdAppConfig;
|
||||
import org.jeecg.config.thirdapp.ThirdAppTypeItemVo;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.system.entity.SysThirdAccount;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.model.ThirdLoginModel;
|
||||
import org.jeecg.modules.system.service.ISysThirdAccountService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppWechatEnterpriseServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
|
@ -30,7 +33,8 @@ import org.springframework.web.bind.annotation.*;
|
|||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -53,6 +57,13 @@ public class ThirdLoginController {
|
|||
@Autowired
|
||||
private AuthRequestFactory factory;
|
||||
|
||||
@Autowired
|
||||
ThirdAppConfig thirdAppConfig;
|
||||
@Autowired
|
||||
private ThirdAppWechatEnterpriseServiceImpl thirdAppWechatEnterpriseService;
|
||||
@Autowired
|
||||
private ThirdAppDingtalkServiceImpl thirdAppDingtalkService;
|
||||
|
||||
@RequestMapping("/render/{source}")
|
||||
public void render(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
|
||||
log.info("第三方登录进入render:" + source);
|
||||
|
@ -86,7 +97,7 @@ public class ThirdLoginController {
|
|||
SysThirdAccount user = null;
|
||||
if(thridList==null || thridList.size()==0) {
|
||||
//否则直接创建新账号
|
||||
user = saveThirdUser(tlm);
|
||||
user = sysThirdAccountService.saveThirdUser(tlm);
|
||||
}else {
|
||||
//已存在 只设置用户名 不设置头像
|
||||
user = thridList.get(0);
|
||||
|
@ -130,7 +141,7 @@ public class ThirdLoginController {
|
|||
}
|
||||
//创建新账号
|
||||
//update-begin-author:wangshuai date:20201118 for:修改成从第三方登录查出来的user_id,在查询用户表尽行token
|
||||
SysThirdAccount user = saveThirdUser(model);
|
||||
SysThirdAccount user = sysThirdAccountService.saveThirdUser(model);
|
||||
if(oConvertUtils.isNotEmpty(user.getSysUserId())){
|
||||
String sysUserId = user.getSysUserId();
|
||||
SysUser sysUser = sysUserService.getById(sysUserId);
|
||||
|
@ -182,22 +193,6 @@ public class ThirdLoginController {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新用户
|
||||
* @param tlm 第三方登录信息
|
||||
*/
|
||||
private SysThirdAccount saveThirdUser(ThirdLoginModel tlm){
|
||||
SysThirdAccount user = new SysThirdAccount();
|
||||
user.setDelFlag(CommonConstant.DEL_FLAG_0);
|
||||
user.setStatus(1);
|
||||
user.setThirdType(tlm.getSource());
|
||||
user.setAvatar(tlm.getAvatar());
|
||||
user.setRealname(tlm.getUsername());
|
||||
user.setThirdUserUuid(tlm.getUuid());
|
||||
sysThirdAccountService.save(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
private String saveToken(SysUser user) {
|
||||
// 生成token
|
||||
String token = JwtUtil.sign(user.getUsername(), user.getPassword());
|
||||
|
@ -277,4 +272,118 @@ public class ThirdLoginController {
|
|||
result.setResult(token);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信/钉钉 OAuth2登录
|
||||
*
|
||||
* @param source
|
||||
* @param state
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("/oauth2/{source}/login")
|
||||
public String oauth2LoginCallback(@PathVariable("source") String source, @RequestParam("state") String state, HttpServletResponse response) throws Exception {
|
||||
String url;
|
||||
if (ThirdAppConfig.WECHAT_ENTERPRISE.equalsIgnoreCase(source)) {
|
||||
ThirdAppTypeItemVo config = thirdAppConfig.getWechatEnterprise();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
// 构造企业微信OAuth2登录授权地址
|
||||
builder.append("https://open.weixin.qq.com/connect/oauth2/authorize");
|
||||
// 企业的CorpID
|
||||
builder.append("?appid=").append(config.getClientId());
|
||||
// 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
|
||||
String redirectUri = RestUtil.getBaseUrl() + "/sys/thirdLogin/oauth2/wechat_enterprise/callback";
|
||||
builder.append("&redirect_uri=").append(URLEncoder.encode(redirectUri, "UTF-8"));
|
||||
// 返回类型,此时固定为:code
|
||||
builder.append("&response_type=code");
|
||||
// 应用授权作用域。
|
||||
// snsapi_base:静默授权,可获取成员的的基础信息(UserId与DeviceId);
|
||||
builder.append("&scope=snsapi_base");
|
||||
// 重定向后会带上state参数,长度不可超过128个字节
|
||||
builder.append("&state=").append(state);
|
||||
// 终端使用此参数判断是否需要带上身份信息
|
||||
builder.append("#wechat_redirect");
|
||||
url = builder.toString();
|
||||
} else if (ThirdAppConfig.DINGTALK.equalsIgnoreCase(source)) {
|
||||
ThirdAppTypeItemVo config = thirdAppConfig.getDingtalk();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
// 构造钉钉OAuth2登录授权地址
|
||||
builder.append("https://login.dingtalk.com/oauth2/auth");
|
||||
// 授权通过/拒绝后回调地址。
|
||||
// 注意 需要与注册应用时登记的域名保持一致。
|
||||
String redirectUri = RestUtil.getBaseUrl() + "/sys/thirdLogin/oauth2/dingtalk/callback";
|
||||
builder.append("?redirect_uri=").append(URLEncoder.encode(redirectUri, "UTF-8"));
|
||||
// 固定值为code。
|
||||
// 授权通过后返回authCode。
|
||||
builder.append("&response_type=code");
|
||||
// 步骤一中创建的应用详情中获取。
|
||||
// 企业内部应用:client_id为应用的AppKey。
|
||||
builder.append("&client_id=").append(config.getClientId());
|
||||
// 授权范围,授权页面显示的授权信息以应用注册时配置的为准。
|
||||
// openid:授权后可获得用户userid
|
||||
builder.append("&scope=openid");
|
||||
// 跟随authCode原样返回。
|
||||
builder.append("&state=").append(state);
|
||||
url = builder.toString();
|
||||
} else {
|
||||
return "不支持的source";
|
||||
}
|
||||
log.info("oauth2 login url:" + url);
|
||||
response.sendRedirect(url);
|
||||
return "login…";
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信/钉钉 OAuth2登录回调
|
||||
*
|
||||
* @param code
|
||||
* @param state
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("/oauth2/{source}/callback")
|
||||
public String oauth2LoginCallback(
|
||||
@PathVariable("source") String source,
|
||||
// 企业微信返回的code
|
||||
@RequestParam(value = "code", required = false) String code,
|
||||
// 钉钉返回的code
|
||||
@RequestParam(value = "authCode", required = false) String authCode,
|
||||
@RequestParam("state") String state,
|
||||
HttpServletResponse response
|
||||
) {
|
||||
SysUser loginUser;
|
||||
if (ThirdAppConfig.WECHAT_ENTERPRISE.equalsIgnoreCase(source)) {
|
||||
log.info("【企业微信】OAuth2登录进入callback:code=" + code + ", state=" + state);
|
||||
loginUser = thirdAppWechatEnterpriseService.oauth2Login(code);
|
||||
if (loginUser == null) {
|
||||
return "登录失败";
|
||||
}
|
||||
} else if (ThirdAppConfig.DINGTALK.equalsIgnoreCase(source)) {
|
||||
log.info("【钉钉】OAuth2登录进入callback:authCode=" + authCode + ", state=" + state);
|
||||
loginUser = thirdAppDingtalkService.oauth2Login(authCode);
|
||||
if (loginUser == null) {
|
||||
return "登录失败";
|
||||
}
|
||||
} else {
|
||||
return "不支持的source";
|
||||
}
|
||||
try {
|
||||
String token = saveToken(loginUser);
|
||||
state += "/oauth2-app/login?oauth2LoginToken=" + URLEncoder.encode(token, "UTF-8");
|
||||
state += "&thirdType=" + "wechat_enterprise";
|
||||
log.info("OAuth2登录重定向地址: " + state);
|
||||
try {
|
||||
response.sendRedirect(state);
|
||||
return "ok";
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "重定向失败";
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
return "解码失败";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +1,20 @@
|
|||
package org.jeecg.modules.system.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
import org.jeecg.common.system.vo.DictModelMany;
|
||||
import org.jeecg.common.system.vo.DictQuery;
|
||||
import org.jeecg.modules.system.entity.SysDict;
|
||||
import org.jeecg.modules.system.model.DuplicateCheckVo;
|
||||
import org.jeecg.modules.system.model.TreeSelectModel;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -30,11 +30,29 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
|
|||
* 重复检查SQL
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public Long duplicateCheckCountSql(DuplicateCheckVo duplicateCheckVo);
|
||||
@Deprecated
|
||||
public Long duplicateCheckCountSqlNoDataId(DuplicateCheckVo duplicateCheckVo);
|
||||
|
||||
public List<DictModel> queryDictItemsByCode(@Param("code") String code);
|
||||
|
||||
/**
|
||||
* 查询有效的数据字典项
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> queryEnableDictItemsByCode(@Param("code") String code);
|
||||
|
||||
|
||||
/**
|
||||
* 通过多个字典code获取字典数据
|
||||
*
|
||||
* @param dictCodeList
|
||||
* @return
|
||||
*/
|
||||
public List<DictModelMany> queryDictItemsByCodeList(@Param("dictCodeList") List<String> dictCodeList);
|
||||
|
||||
@Deprecated
|
||||
public List<DictModel> queryTableDictItemsByCode(@Param("table") String table,@Param("text") String text,@Param("code") String code);
|
||||
|
||||
|
@ -47,9 +65,29 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
|
|||
|
||||
public String queryDictTextByKey(@Param("code") String code,@Param("key") String key);
|
||||
|
||||
/**
|
||||
* 可通过多个字典code查询翻译文本
|
||||
* @param dictCodeList 多个字典code
|
||||
* @param keys 数据列表
|
||||
* @return
|
||||
*/
|
||||
List<DictModelMany> queryManyDictByKeys(@Param("dictCodeList") List<String> dictCodeList, @Param("keys") List<String> keys);
|
||||
|
||||
@Deprecated
|
||||
public String queryTableDictTextByKey(@Param("table") String table,@Param("text") String text,@Param("code") String code,@Param("key") String key);
|
||||
|
||||
/**
|
||||
* 通过查询指定table的 text code key 获取字典值,可批量查询
|
||||
*
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
List<DictModel> queryTableDictTextByKeys(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("keys") List<String> keys);
|
||||
|
||||
@Deprecated
|
||||
public List<DictModel> queryTableDictByKeys(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("keyArray") String[] keyArray);
|
||||
|
||||
|
@ -142,6 +180,7 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
|
|||
* @param filterSql
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
IPage<DictModel> queryTableDictWithFilter(Page<DictModel> page, @Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql);
|
||||
|
||||
/**
|
||||
|
@ -152,5 +191,6 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
|
|||
* @param filterSql
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
List<DictModel> queryAllTableDictItems(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql);
|
||||
}
|
||||
|
|
|
@ -131,6 +131,7 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
|
|||
int deleteLogicDeleted(@Param("userIds") String userIds);
|
||||
|
||||
/** 更新空字符串为null【此写法有sql注入风险,禁止随便用】 */
|
||||
@Deprecated
|
||||
int updateNullByEmptyString(@Param("fieldName") String fieldName);
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,31 @@
|
|||
order by s.sort_order asc
|
||||
</select>
|
||||
|
||||
<!-- 通过字典code获取有效的字典数据项 -->
|
||||
<select id="queryEnableDictItemsByCode" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
|
||||
select s.item_value as "value",s.item_text as "text" from sys_dict_item s
|
||||
where dict_id = (select id from sys_dict where dict_code = #{code})
|
||||
and s.status = 1
|
||||
order by s.sort_order asc
|
||||
</select>
|
||||
|
||||
<!-- 通过多个字典code获取字典数据 -->
|
||||
<select id="queryDictItemsByCodeList" parameterType="String" resultType="org.jeecg.common.system.vo.DictModelMany">
|
||||
SELECT
|
||||
dict.dict_code,
|
||||
item.item_text AS "text",
|
||||
item.item_value AS "value"
|
||||
FROM
|
||||
sys_dict_item item
|
||||
INNER JOIN sys_dict dict ON dict.id = item.dict_id
|
||||
WHERE dict.dict_code IN (
|
||||
<foreach item="dictCode" collection="dictCodeList" separator=",">
|
||||
#{dictCode}
|
||||
</foreach>
|
||||
)
|
||||
ORDER BY item.sort_order ASC
|
||||
</select>
|
||||
|
||||
<!-- 通过字典code获取字典数据 -->
|
||||
<select id="queryDictTextByKey" parameterType="String" resultType="String">
|
||||
select s.item_text from sys_dict_item s
|
||||
|
@ -16,6 +41,26 @@
|
|||
and s.item_value = #{key}
|
||||
</select>
|
||||
|
||||
<!-- 通过字典code获取字典数据,可批量查询 -->
|
||||
<select id="queryManyDictByKeys" parameterType="String" resultType="org.jeecg.common.system.vo.DictModelMany">
|
||||
SELECT
|
||||
dict.dict_code,
|
||||
item.item_text AS "text",
|
||||
item.item_value AS "value"
|
||||
FROM
|
||||
sys_dict_item item
|
||||
INNER JOIN sys_dict dict ON dict.id = item.dict_id
|
||||
WHERE dict.dict_code IN (
|
||||
<foreach item="dictCode" collection="dictCodeList" separator=",">
|
||||
#{dictCode}
|
||||
</foreach>
|
||||
)
|
||||
AND item.item_value IN (
|
||||
<foreach item="key" collection="keys" separator=",">
|
||||
#{key}
|
||||
</foreach>
|
||||
)
|
||||
</select>
|
||||
|
||||
<!--通过查询指定table的 text code 获取字典-->
|
||||
<select id="queryTableDictItemsByCode" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
|
||||
|
@ -35,6 +80,15 @@
|
|||
select ${text} as "text" from ${table} where ${code}= #{key}
|
||||
</select>
|
||||
|
||||
<!--通过查询指定table的 text code key 获取字典值,可批量查询-->
|
||||
<select id="queryTableDictTextByKeys" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
|
||||
select ${text} as "text", ${code} as "value" from ${table} where ${code} IN (
|
||||
<foreach item="key" collection="keys" separator=",">
|
||||
#{key}
|
||||
</foreach>
|
||||
)
|
||||
</select>
|
||||
|
||||
<!--通过查询指定table的 text code key 获取字典值,包含value-->
|
||||
<select id="queryTableDictByKeys" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
|
||||
select ${text} as "text", ${code} as "value" from ${table} where ${code} in
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
<!-- 首页访问统计 -->
|
||||
<select id="findVisitCount" resultType="java.util.HashMap">
|
||||
<if test="dbType == 'MYSQL' || dbType == 'MARIADB'">
|
||||
<if test="dbType == 'mysql' || dbType == 'mariadb' || dbType == 'clickhouse'|| dbType == 'sqlite'">
|
||||
select count(*) as visit
|
||||
,count(distinct(ip)) as ip
|
||||
,DATE_FORMAT(create_time, '%Y-%m-%d') as tian
|
||||
|
@ -34,7 +34,7 @@
|
|||
group by tian,type
|
||||
order by tian asc
|
||||
</if>
|
||||
<if test="dbType == 'ORACLE' || dbType == 'DM'">
|
||||
<if test="dbType == 'oracle' || dbType == 'oracle12c' || dbType == 'dm'">
|
||||
select count(*) as visit
|
||||
,count(distinct(ip)) as ip
|
||||
,to_char(create_time, 'yyyy-mm-dd') as tian
|
||||
|
@ -44,7 +44,7 @@
|
|||
group by to_char(create_time, 'yyyy-mm-dd'),to_char(create_time, 'mm-dd')
|
||||
order by to_char(create_time, 'yyyy-mm-dd') asc
|
||||
</if>
|
||||
<if test="dbType == 'POSTGRESQL'">
|
||||
<if test="dbType == 'postgresql' || dbType == 'kingbasees' || dbType == 'zenith'">
|
||||
select count(*) as visit
|
||||
,count(distinct(ip)) as ip
|
||||
,to_char(create_time, 'yyyy-mm-dd') as tian
|
||||
|
@ -54,7 +54,7 @@
|
|||
group by tian,type
|
||||
order by tian asc
|
||||
</if>
|
||||
<if test="dbType == 'SQLSERVER'">
|
||||
<if test="dbType == 'sqlserver' || dbType == 'sqlserver2005'">
|
||||
select count(*) as visit
|
||||
,count(distinct(ip)) as ip
|
||||
,CONVERT(varchar(100), create_time, 23) as tian
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<select id="selectThirdIdsByUsername" resultType="org.jeecg.modules.system.entity.SysThirdAccount">
|
||||
SELECT third_user_id FROM sys_third_account
|
||||
INNER JOIN sys_user ON sys_user.id = sys_third_account.sys_user_id
|
||||
WHERE third_type = #{thirdType} AND
|
||||
WHERE sys_third_account.third_type = #{thirdType} AND
|
||||
<!-- TODO in 查询数据量大的时候可能会报错 -->
|
||||
<foreach collection="sysUsernameArr" item="item" open=" sys_user.username IN (" close=")" separator=",">#{item}</foreach>
|
||||
</select>
|
||||
|
|
|
@ -22,6 +22,21 @@ public interface ISysDictService extends IService<SysDict> {
|
|||
|
||||
public List<DictModel> queryDictItemsByCode(String code);
|
||||
|
||||
/**
|
||||
* 查询有效的数据字典项
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> queryEnableDictItemsByCode(String code);
|
||||
|
||||
/**
|
||||
* 通过多个字典code获取字典数据
|
||||
*
|
||||
* @param dictCodeList
|
||||
* @return key = 字典code,value=对应的字典选项
|
||||
*/
|
||||
Map<String, List<DictModel>> queryDictItemsByCodeList(List<String> dictCodeList);
|
||||
|
||||
public Map<String,List<DictModel>> queryAllDictItems();
|
||||
|
||||
@Deprecated
|
||||
|
@ -32,9 +47,28 @@ public interface ISysDictService extends IService<SysDict> {
|
|||
|
||||
public String queryDictTextByKey(String code, String key);
|
||||
|
||||
/**
|
||||
* 可通过多个字典code查询翻译文本
|
||||
* @param dictCodeList 多个字典code
|
||||
* @param keys 数据列表
|
||||
* @return
|
||||
*/
|
||||
Map<String, List<DictModel>> queryManyDictByKeys(List<String> dictCodeList, List<String> keys);
|
||||
|
||||
@Deprecated
|
||||
String queryTableDictTextByKey(String table, String text, String code, String key);
|
||||
|
||||
/**
|
||||
* 通过查询指定table的 text code key 获取字典值,可批量查询
|
||||
*
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> queryTableDictTextByKeys(String table, String text, String code, List<String> keys);
|
||||
|
||||
@Deprecated
|
||||
List<String> queryTableDictByKeys(String table, String text, String code, String keys);
|
||||
@Deprecated
|
||||
|
|
|
@ -3,6 +3,33 @@ package org.jeecg.modules.system.service;
|
|||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.system.entity.SysTenant;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface ISysTenantService extends IService<SysTenant> {
|
||||
|
||||
/**
|
||||
* 查询有效的租户
|
||||
*
|
||||
* @param idList
|
||||
* @return
|
||||
*/
|
||||
List<SysTenant> queryEffectiveTenant(Collection<String> idList);
|
||||
|
||||
/**
|
||||
* 返回某个租户被多少个用户引用了
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
int countUserLinkTenant(String id);
|
||||
|
||||
/**
|
||||
* 根据ID删除租户,会判断是否已被引用
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
boolean removeTenantById(String id);
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.jeecg.modules.system.service;
|
|||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.system.entity.SysThirdAccount;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.model.ThirdLoginModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -32,4 +33,11 @@ public interface ISysThirdAccountService extends IService<SysThirdAccount> {
|
|||
*/
|
||||
List<SysThirdAccount> listThirdUserIdByUsername(String[] sysUsernameArr, String thirdType);
|
||||
|
||||
/**
|
||||
* 创建新用户
|
||||
*
|
||||
* @param tlm 第三方登录信息
|
||||
*/
|
||||
SysThirdAccount saveThirdUser(ThirdLoginModel tlm);
|
||||
|
||||
}
|
||||
|
|
|
@ -97,6 +97,9 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
|||
@Autowired
|
||||
private ThirdAppDingtalkServiceImpl dingtalkService;
|
||||
|
||||
@Autowired
|
||||
ISysCategoryService sysCategoryService;
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames=CacheConstant.SYS_USERS_CACHE, key="#username")
|
||||
public LoginUser getUserByName(String username) {
|
||||
|
@ -276,6 +279,12 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
|||
return sysDictService.queryDictItemsByCode(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = CacheConstant.SYS_ENABLE_DICT_CACHE,key = "#code", unless = "#result == null ")
|
||||
public List<DictModel> queryEnableDictItemsByCode(String code) {
|
||||
return sysDictService.queryEnableDictItemsByCode(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> queryTableDictItemsByCode(String table, String text, String code) {
|
||||
//update-begin-author:taoyan date:20200820 for:【Online+系统】字典表加权限控制机制逻辑,想法不错 LOWCOD-799
|
||||
|
@ -1067,4 +1076,80 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分类字典翻译
|
||||
*
|
||||
* @param ids 分类字典表id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> loadCategoryDictItem(String ids) {
|
||||
return sysCategoryService.loadDictItem(ids, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典code加载字典text
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param keys 要查询的key
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> loadDictItem(String dictCode, String keys) {
|
||||
String[] params = dictCode.split(",");
|
||||
return sysDictService.queryTableDictByKeys(params[0], params[1], params[2], keys, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典code查询字典项
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param dictCode 要查询的key
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<DictModel> getDictItems(String dictCode) {
|
||||
List<DictModel> ls = sysDictService.getDictItems(dictCode);
|
||||
if (ls == null) {
|
||||
ls = new ArrayList<>();
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据多个字典code查询多个字典项
|
||||
*
|
||||
* @param dictCodeList
|
||||
* @return key = dictCode ; value=对应的字典项
|
||||
*/
|
||||
@Override
|
||||
public Map<String, List<DictModel>> getManyDictItems(List<String> dictCodeList) {
|
||||
return sysDictService.queryDictItemsByCodeList(dictCodeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【下拉搜索】
|
||||
* 大数据量的字典表 走异步加载,即前端输入内容过滤数据
|
||||
*
|
||||
* @param dictCode 字典code格式:table,text,code
|
||||
* @param keyword 过滤关键字
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize) {
|
||||
return sysDictService.loadDict(dictCode, keyword, pageSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys) {
|
||||
List<String> dictCodeList = Arrays.asList(dictCodes.split(","));
|
||||
List<String> values = Arrays.asList(keys.split(","));
|
||||
return sysDictService.queryManyDictByKeys(dictCodeList, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys) {
|
||||
return sysDictService.queryTableDictTextByKeys(table, text, code, Arrays.asList(keys.split(",")));
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.jeecg.common.constant.CacheConstant;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
import org.jeecg.common.system.vo.DictModelMany;
|
||||
import org.jeecg.common.system.vo.DictQuery;
|
||||
import org.jeecg.common.util.SqlInjectionUtil;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
|
@ -57,6 +58,25 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||
return sysDictMapper.queryDictItemsByCode(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = CacheConstant.SYS_ENABLE_DICT_CACHE,key = "#code", unless = "#result == null ")
|
||||
public List<DictModel> queryEnableDictItemsByCode(String code) {
|
||||
log.debug("无缓存dictCache的时候调用这里!");
|
||||
return sysDictMapper.queryEnableDictItemsByCode(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<DictModel>> queryDictItemsByCodeList(List<String> dictCodeList) {
|
||||
List<DictModelMany> list = sysDictMapper.queryDictItemsByCodeList(dictCodeList);
|
||||
Map<String, List<DictModel>> dictMap = new HashMap<>();
|
||||
for (DictModelMany dict : list) {
|
||||
List<DictModel> dictItemList = dictMap.computeIfAbsent(dict.getDictCode(), i -> new ArrayList<>());
|
||||
dict.setDictCode(null);
|
||||
dictItemList.add(new DictModel(dict.getValue(), dict.getText()));
|
||||
}
|
||||
return dictMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<DictModel>> queryAllDictItems() {
|
||||
Map<String, List<DictModel>> res = new HashMap<String, List<DictModel>>();
|
||||
|
@ -93,6 +113,17 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||
return sysDictMapper.queryDictTextByKey(code, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<DictModel>> queryManyDictByKeys(List<String> dictCodeList, List<String> keys) {
|
||||
List<DictModelMany> list = sysDictMapper.queryManyDictByKeys(dictCodeList, keys);
|
||||
Map<String, List<DictModel>> dictMap = new HashMap<>();
|
||||
for (DictModelMany dict : list) {
|
||||
List<DictModel> dictItemList = dictMap.computeIfAbsent(dict.getDictCode(), i -> new ArrayList<>());
|
||||
dictItemList.add(new DictModel(dict.getValue(), dict.getText()));
|
||||
}
|
||||
return dictMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过查询指定table的 text code 获取字典
|
||||
* dictTableCache采用redis缓存有效期10分钟
|
||||
|
@ -130,6 +161,11 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||
return sysDictMapper.queryTableDictTextByKey(table,text,code,key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> queryTableDictTextByKeys(String table, String text, String code, List<String> keys) {
|
||||
return sysDictMapper.queryTableDictTextByKeys(table, text, code, keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> queryTableDictByKeys(String table, String text, String code, String keys) {
|
||||
return this.queryTableDictByKeys(table, text, code, keys, true);
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.Map;
|
|||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.util.CommonUtils;
|
||||
import org.jeecg.modules.system.entity.SysLog;
|
||||
|
@ -60,7 +61,7 @@ public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> impleme
|
|||
|
||||
@Override
|
||||
public List<Map<String,Object>> findVisitCount(Date dayStart, Date dayEnd) {
|
||||
String dbType = CommonUtils.getDatabaseType();
|
||||
return sysLogMapper.findVisitCount(dayStart, dayEnd,dbType);
|
||||
DbType dbType = CommonUtils.getDatabaseTypeEnum();
|
||||
return sysLogMapper.findVisitCount(dayStart, dayEnd,dbType.getDb());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,56 @@
|
|||
package org.jeecg.modules.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.modules.system.entity.SysTenant;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.mapper.SysTenantMapper;
|
||||
import org.jeecg.modules.system.service.ISysTenantService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Service("sysTenantServiceImpl")
|
||||
@Slf4j
|
||||
public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant> implements ISysTenantService {
|
||||
|
||||
@Autowired
|
||||
ISysUserService userService;
|
||||
|
||||
@Override
|
||||
public List<SysTenant> queryEffectiveTenant(Collection<String> idList) {
|
||||
LambdaQueryWrapper<SysTenant> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(SysTenant::getId, idList);
|
||||
queryWrapper.eq(SysTenant::getStatus, CommonConstant.STATUS_1);
|
||||
//此处查询忽略时间条件
|
||||
return super.list(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countUserLinkTenant(String id) {
|
||||
LambdaQueryWrapper<SysUser> userQueryWrapper = new LambdaQueryWrapper<>();
|
||||
userQueryWrapper.eq(SysUser::getRelTenantIds, id);
|
||||
userQueryWrapper.or().like(SysUser::getRelTenantIds, "%," + id);
|
||||
userQueryWrapper.or().like(SysUser::getRelTenantIds, id + ",%");
|
||||
userQueryWrapper.or().like(SysUser::getRelTenantIds, "%," + id + ",%");
|
||||
// 查找出已被关联的用户数量
|
||||
return userService.count(userQueryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeTenantById(String id) {
|
||||
// 查找出已被关联的用户数量
|
||||
int userCount = this.countUserLinkTenant(id);
|
||||
if (userCount > 0) {
|
||||
throw new JeecgBootException("该租户已被引用,无法删除!");
|
||||
}
|
||||
return super.removeById(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.jeecg.modules.system.mapper.SysRoleMapper;
|
|||
import org.jeecg.modules.system.mapper.SysThirdAccountMapper;
|
||||
import org.jeecg.modules.system.mapper.SysUserMapper;
|
||||
import org.jeecg.modules.system.mapper.SysUserRoleMapper;
|
||||
import org.jeecg.modules.system.model.ThirdLoginModel;
|
||||
import org.jeecg.modules.system.service.ISysThirdAccountService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -133,4 +134,18 @@ public class SysThirdAccountServiceImpl extends ServiceImpl<SysThirdAccountMappe
|
|||
return sysThirdAccountMapper.selectThirdIdsByUsername(sysUsernameArr, thirdType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysThirdAccount saveThirdUser(ThirdLoginModel tlm) {
|
||||
SysThirdAccount user = new SysThirdAccount();
|
||||
user.setDelFlag(CommonConstant.DEL_FLAG_0);
|
||||
user.setStatus(1);
|
||||
user.setThirdType(tlm.getSource());
|
||||
user.setAvatar(tlm.getAvatar());
|
||||
user.setRealname(tlm.getUsername());
|
||||
user.setThirdUserUuid(tlm.getUuid());
|
||||
user.setThirdUserId(tlm.getUuid());
|
||||
super.save(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.jeecg.modules.system.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.jeecg.dingtalk.api.base.JdtBaseAPI;
|
||||
|
@ -12,6 +13,8 @@ import com.jeecg.dingtalk.api.message.JdtMessageAPI;
|
|||
import com.jeecg.dingtalk.api.message.vo.ActionCardMessage;
|
||||
import com.jeecg.dingtalk.api.message.vo.Message;
|
||||
import com.jeecg.dingtalk.api.message.vo.TextMessage;
|
||||
import com.jeecg.dingtalk.api.oauth2.JdtOauth2API;
|
||||
import com.jeecg.dingtalk.api.oauth2.vo.ContactUser;
|
||||
import com.jeecg.dingtalk.api.user.JdtUserAPI;
|
||||
import com.jeecg.dingtalk.api.user.body.GetUserListBody;
|
||||
import com.jeecg.dingtalk.api.user.vo.User;
|
||||
|
@ -25,9 +28,11 @@ import org.jeecg.common.util.RestUtil;
|
|||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.thirdapp.ThirdAppConfig;
|
||||
import org.jeecg.config.thirdapp.ThirdAppTypeItemVo;
|
||||
import org.jeecg.modules.system.entity.*;
|
||||
import org.jeecg.modules.system.mapper.SysAnnouncementSendMapper;
|
||||
import org.jeecg.modules.system.model.SysDepartTreeModel;
|
||||
import org.jeecg.modules.system.model.ThirdLoginModel;
|
||||
import org.jeecg.modules.system.service.*;
|
||||
import org.jeecg.modules.system.vo.thirdapp.JdtDepartmentTreeVo;
|
||||
import org.jeecg.modules.system.vo.thirdapp.SyncInfoVo;
|
||||
|
@ -65,6 +70,9 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
@Autowired
|
||||
private SysAnnouncementSendMapper sysAnnouncementSendMapper;
|
||||
|
||||
// 第三方APP类型,当前固定为 dingtalk
|
||||
public final String THIRD_TYPE = ThirdAppConfig.DINGTALK.toLowerCase();
|
||||
|
||||
@Override
|
||||
public String getAccessToken() {
|
||||
String appKey = thirdAppConfig.getDingtalk().getClientId();
|
||||
|
@ -273,7 +281,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
* 1. 查询 sys_third_account(第三方账号表)是否有数据,如果有代表已同步
|
||||
* 2. 本地表里没有,就先用手机号判断,不通过再用username判断。
|
||||
*/
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneBySysUserId(sysUser.getId(), ThirdAppConfig.DINGTALK.toLowerCase());
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneBySysUserId(sysUser.getId(), THIRD_TYPE);
|
||||
if (sysThirdAccount != null && oConvertUtils.isNotEmpty(sysThirdAccount.getThirdUserId())) {
|
||||
// sys_third_account 表匹配成功,通过第三方userId查询出第三方userInfo
|
||||
dtUserInfo = JdtUserAPI.getUserById(sysThirdAccount.getThirdUserId(), accessToken);
|
||||
|
@ -315,7 +323,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
sysThirdAccount.setSysUserId(sysUser.getId());
|
||||
sysThirdAccount.setStatus(1);
|
||||
sysThirdAccount.setDelFlag(0);
|
||||
sysThirdAccount.setThirdType(ThirdAppConfig.DINGTALK.toLowerCase());
|
||||
sysThirdAccount.setThirdType(THIRD_TYPE);
|
||||
}
|
||||
// 设置第三方app用户ID
|
||||
sysThirdAccount.setThirdUserId(dtUserId);
|
||||
|
@ -343,7 +351,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
List<User> ddUserList = this.getDtAllUserByDepartment(allDepartment, accessToken);
|
||||
|
||||
for (User dtUserInfo : ddUserList) {
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneByThirdUserId(dtUserInfo.getUserid(), ThirdAppConfig.DINGTALK.toLowerCase());
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneByThirdUserId(dtUserInfo.getUserid(), THIRD_TYPE);
|
||||
List<SysUser> collect = sysUsersList.stream().filter(user -> (dtUserInfo.getMobile().equals(user.getPhone()) || dtUserInfo.getUserid().equals(user.getUsername()))
|
||||
).collect(Collectors.toList());
|
||||
if (collect != null && collect.size() > 0) {
|
||||
|
@ -414,7 +422,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
sysThirdAccount.setSysUserId(sysUserId);
|
||||
sysThirdAccount.setStatus(1);
|
||||
sysThirdAccount.setDelFlag(0);
|
||||
sysThirdAccount.setThirdType(ThirdAppConfig.DINGTALK.toLowerCase());
|
||||
sysThirdAccount.setThirdType(THIRD_TYPE);
|
||||
}
|
||||
sysThirdAccount.setThirdUserId(dtUserId);
|
||||
sysThirdAccountService.saveOrUpdate(sysThirdAccount);
|
||||
|
@ -517,6 +525,9 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), password, salt);
|
||||
sysUser.setSalt(salt);
|
||||
sysUser.setPassword(passwordEncode);
|
||||
// update-begin--Author:liusq Date:20210713 for:钉钉同步到本地的人员没有状态,导致同步之后无法登录 #I3ZC2L
|
||||
sysUser.setStatus(1);
|
||||
// update-end--Author:liusq Date:20210713 for:钉钉同步到本地的人员没有状态,导致同步之后无法登录 #I3ZC2L
|
||||
return this.dtUserToSysUser(dtUser, sysUser);
|
||||
}
|
||||
|
||||
|
@ -629,7 +640,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
return count;
|
||||
}
|
||||
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysThirdAccount::getThirdType, ThirdAppConfig.DINGTALK.toLowerCase());
|
||||
queryWrapper.eq(SysThirdAccount::getThirdType, THIRD_TYPE);
|
||||
queryWrapper.in(SysThirdAccount::getSysUserId, userIdList);
|
||||
// 根据userId,获取第三方用户的id
|
||||
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.list(queryWrapper);
|
||||
|
@ -686,7 +697,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
} else {
|
||||
String[] toUsers = message.getToUser().split(",");
|
||||
// 通过第三方账号表查询出第三方userId
|
||||
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(toUsers, ThirdAppConfig.DINGTALK.toLowerCase());
|
||||
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(toUsers, THIRD_TYPE);
|
||||
List<String> dtUserIds = thirdAccountList.stream().map(SysThirdAccount::getThirdUserId).collect(Collectors.toList());
|
||||
textMessage.setUserid_list(dtUserIds);
|
||||
}
|
||||
|
@ -757,7 +768,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
if(userIds!=null){
|
||||
String[] usernameList = sysUserService.userIdToUsername(Arrays.asList(userIds)).toArray(new String[]{});
|
||||
// 通过第三方账号表查询出第三方userId
|
||||
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(usernameList, ThirdAppConfig.DINGTALK.toLowerCase());
|
||||
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(usernameList, THIRD_TYPE);
|
||||
List<String> dtUserIds = thirdAccountList.stream().map(SysThirdAccount::getThirdUserId).collect(Collectors.toList());
|
||||
actionCardMessage.setUserid_list(dtUserIds);
|
||||
return JdtMessageAPI.sendActionCardMessage(actionCardMessage, accessToken);
|
||||
|
@ -766,4 +777,91 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth2登录,成功返回登录的SysUser,失败返回null
|
||||
*/
|
||||
public SysUser oauth2Login(String authCode) {
|
||||
ThirdAppTypeItemVo dtConfig = thirdAppConfig.getDingtalk();
|
||||
// 1. 根据免登授权码获取用户 AccessToken
|
||||
String userAccessToken = JdtOauth2API.getUserAccessToken(dtConfig.getClientId(), dtConfig.getClientSecret(), authCode);
|
||||
if (userAccessToken == null) {
|
||||
log.error("oauth2Login userAccessToken is null");
|
||||
return null;
|
||||
}
|
||||
// 2. 根据用户 AccessToken 获取当前用户的基本信息(不包括userId)
|
||||
ContactUser contactUser = JdtOauth2API.getContactUsers("me", userAccessToken);
|
||||
if (contactUser == null) {
|
||||
log.error("oauth2Login contactUser is null");
|
||||
return null;
|
||||
}
|
||||
String unionId = contactUser.getUnionId();
|
||||
// 3. 根据获取到的 unionId 换取用户 userId
|
||||
String accessToken = this.getAccessToken();
|
||||
if (accessToken == null) {
|
||||
log.error("oauth2Login accessToken is null");
|
||||
return null;
|
||||
}
|
||||
Response<String> getUserIdRes = JdtUserAPI.getUseridByUnionid(unionId, accessToken);
|
||||
if (!getUserIdRes.isSuccess()) {
|
||||
log.error("oauth2Login getUseridByUnionid failed: " + JSON.toJSONString(getUserIdRes));
|
||||
return null;
|
||||
}
|
||||
String appUserId = getUserIdRes.getResult();
|
||||
log.info("appUserId: " + appUserId);
|
||||
if (appUserId != null) {
|
||||
// 判断第三方用户表有没有这个人
|
||||
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysThirdAccount::getThirdUserUuid, appUserId);
|
||||
queryWrapper.or().eq(SysThirdAccount::getThirdUserId, appUserId);
|
||||
queryWrapper.eq(SysThirdAccount::getThirdType, THIRD_TYPE);
|
||||
SysThirdAccount thirdAccount = sysThirdAccountService.getOne(queryWrapper);
|
||||
if (thirdAccount != null) {
|
||||
return this.getSysUserByThird(thirdAccount, null, appUserId, accessToken);
|
||||
} else {
|
||||
// 直接创建新账号
|
||||
User appUser = JdtUserAPI.getUserById(appUserId, accessToken).getResult();
|
||||
ThirdLoginModel tlm = new ThirdLoginModel(THIRD_TYPE, appUser.getUserid(), appUser.getName(), appUser.getAvatar());
|
||||
thirdAccount = sysThirdAccountService.saveThirdUser(tlm);
|
||||
return this.getSysUserByThird(thirdAccount, appUser, null, null);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据第三方账号获取本地账号,如果不存在就创建
|
||||
*
|
||||
* @param thirdAccount
|
||||
* @param appUser
|
||||
* @param appUserId
|
||||
* @param accessToken
|
||||
* @return
|
||||
*/
|
||||
private SysUser getSysUserByThird(SysThirdAccount thirdAccount, User appUser, String appUserId, String accessToken) {
|
||||
String sysUserId = thirdAccount.getSysUserId();
|
||||
if (oConvertUtils.isNotEmpty(sysUserId)) {
|
||||
return sysUserService.getById(sysUserId);
|
||||
} else {
|
||||
// 如果没有 sysUserId ,说明没有绑定账号,获取到手机号之后进行绑定
|
||||
if (appUser == null) {
|
||||
appUser = JdtUserAPI.getUserById(appUserId, accessToken).getResult();
|
||||
}
|
||||
// 判断系统里是否有这个手机号的用户
|
||||
SysUser sysUser = sysUserService.getUserByPhone(appUser.getMobile());
|
||||
if (sysUser != null) {
|
||||
thirdAccount.setAvatar(appUser.getAvatar());
|
||||
thirdAccount.setRealname(appUser.getName());
|
||||
thirdAccount.setThirdUserId(appUser.getUserid());
|
||||
thirdAccount.setThirdUserUuid(appUser.getUserid());
|
||||
thirdAccount.setSysUserId(sysUser.getId());
|
||||
sysThirdAccountService.updateById(thirdAccount);
|
||||
return sysUser;
|
||||
} else {
|
||||
// 没有就走创建逻辑
|
||||
return sysThirdAccountService.createUser(appUser.getMobile(), appUser.getUserid());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -27,6 +27,7 @@ import org.jeecg.config.thirdapp.ThirdAppConfig;
|
|||
import org.jeecg.modules.system.entity.*;
|
||||
import org.jeecg.modules.system.mapper.SysAnnouncementSendMapper;
|
||||
import org.jeecg.modules.system.model.SysDepartTreeModel;
|
||||
import org.jeecg.modules.system.model.ThirdLoginModel;
|
||||
import org.jeecg.modules.system.service.*;
|
||||
import org.jeecg.modules.system.vo.thirdapp.JwDepartmentTreeVo;
|
||||
import org.jeecg.modules.system.vo.thirdapp.SyncInfoVo;
|
||||
|
@ -62,6 +63,9 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
|||
@Autowired
|
||||
private SysAnnouncementSendMapper sysAnnouncementSendMapper;
|
||||
|
||||
// 第三方APP类型,当前固定为 wechat_enterprise
|
||||
public final String THIRD_TYPE = ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase();
|
||||
|
||||
@Override
|
||||
public String getAccessToken() {
|
||||
String CORP_ID = thirdAppConfig.getWechatEnterprise().getClientId();
|
||||
|
@ -302,7 +306,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
|||
* 2. 本地表里没有,就先用手机号判断,不通过再用username判断。
|
||||
*/
|
||||
User qwUser;
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneBySysUserId(sysUser.getId(), ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneBySysUserId(sysUser.getId(), THIRD_TYPE);
|
||||
for (User qwUserTemp : qwUsers) {
|
||||
if (sysThirdAccount == null || oConvertUtils.isEmpty(sysThirdAccount.getThirdUserId()) || !sysThirdAccount.getThirdUserId().equals(qwUserTemp.getUserid())) {
|
||||
// sys_third_account 表匹配失败,尝试用手机号匹配
|
||||
|
@ -360,7 +364,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
|||
* 1. 查询 sys_third_account(第三方账号表)是否有数据,如果有代表已同步
|
||||
* 2. 本地表里没有,就先用手机号判断,不通过再用username判断。
|
||||
*/
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneByThirdUserId(qwUser.getUserid(), ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneByThirdUserId(qwUser.getUserid(), THIRD_TYPE);
|
||||
List<SysUser> collect = sysUsersList.stream().filter(user -> (qwUser.getMobile().equals(user.getPhone()) || qwUser.getUserid().equals(user.getUsername()))
|
||||
).collect(Collectors.toList());
|
||||
|
||||
|
@ -407,7 +411,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
|||
sysThirdAccount.setSysUserId(sysUserId);
|
||||
sysThirdAccount.setStatus(1);
|
||||
sysThirdAccount.setDelFlag(0);
|
||||
sysThirdAccount.setThirdType(ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
|
||||
sysThirdAccount.setThirdType(THIRD_TYPE);
|
||||
}
|
||||
sysThirdAccount.setThirdUserId(qwUserId);
|
||||
sysThirdAccountService.saveOrUpdate(sysThirdAccount);
|
||||
|
@ -581,6 +585,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
|||
private SysUser qwUserToSysUser(User user) {
|
||||
SysUser sysUser = new SysUser();
|
||||
sysUser.setDelFlag(0);
|
||||
sysUser.setStatus(1);
|
||||
// 通过 username 来关联
|
||||
sysUser.setUsername(user.getUserid());
|
||||
// 密码默认为 “123456”,随机加盐
|
||||
|
@ -680,7 +685,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
|||
return count;
|
||||
}
|
||||
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysThirdAccount::getThirdType, ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
|
||||
queryWrapper.eq(SysThirdAccount::getThirdType, THIRD_TYPE);
|
||||
queryWrapper.in(SysThirdAccount::getSysUserId, userIdList);
|
||||
// 根据userId,获取第三方用户的id
|
||||
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.list(queryWrapper);
|
||||
|
@ -781,11 +786,93 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
|||
} else {
|
||||
String[] toUsers = origin.split(",");
|
||||
// 通过第三方账号表查询出第三方userId
|
||||
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(toUsers, ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
|
||||
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(toUsers, THIRD_TYPE);
|
||||
List<String> toUserList = thirdAccountList.stream().map(SysThirdAccount::getThirdUserId).collect(Collectors.toList());
|
||||
// 多个接收者用‘|’分隔
|
||||
return String.join("|", toUserList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据第三方登录获取到的code来获取第三方app的用户ID
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public String getUserIdByThirdCode(String code, String accessToken) {
|
||||
JSONObject response = JwUserAPI.getUserInfoByCode(code, accessToken);
|
||||
if (response != null) {
|
||||
log.info("response: " + response.toJSONString());
|
||||
if (response.getIntValue("errcode") == 0) {
|
||||
return response.getString("UserId");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth2登录,成功返回登录的SysUser,失败返回null
|
||||
*/
|
||||
public SysUser oauth2Login(String code) {
|
||||
String accessToken = this.getAppAccessToken();
|
||||
if (accessToken == null) {
|
||||
return null;
|
||||
}
|
||||
String appUserId = this.getUserIdByThirdCode(code, accessToken);
|
||||
if (appUserId != null) {
|
||||
// 判断第三方用户表有没有这个人
|
||||
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysThirdAccount::getThirdUserUuid, appUserId);
|
||||
queryWrapper.or().eq(SysThirdAccount::getThirdUserId, appUserId);
|
||||
queryWrapper.eq(SysThirdAccount::getThirdType, THIRD_TYPE);
|
||||
SysThirdAccount thirdAccount = sysThirdAccountService.getOne(queryWrapper);
|
||||
if (thirdAccount != null) {
|
||||
return this.getSysUserByThird(thirdAccount, null, appUserId, accessToken);
|
||||
} else {
|
||||
// 直接创建新账号
|
||||
User appUser = JwUserAPI.getUserByUserid(appUserId, accessToken);
|
||||
ThirdLoginModel tlm = new ThirdLoginModel(THIRD_TYPE, appUser.getUserid(), appUser.getName(), appUser.getAvatar());
|
||||
thirdAccount = sysThirdAccountService.saveThirdUser(tlm);
|
||||
return this.getSysUserByThird(thirdAccount, appUser, null, null);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据第三方账号获取本地账号,如果不存在就创建
|
||||
*
|
||||
* @param thirdAccount
|
||||
* @param appUser
|
||||
* @param appUserId
|
||||
* @param accessToken
|
||||
* @return
|
||||
*/
|
||||
private SysUser getSysUserByThird(SysThirdAccount thirdAccount, User appUser, String appUserId, String accessToken) {
|
||||
String sysUserId = thirdAccount.getSysUserId();
|
||||
if (oConvertUtils.isNotEmpty(sysUserId)) {
|
||||
return sysUserService.getById(sysUserId);
|
||||
} else {
|
||||
// 如果没有 sysUserId ,说明没有绑定账号,获取到手机号之后进行绑定
|
||||
if (appUser == null) {
|
||||
appUser = JwUserAPI.getUserByUserid(appUserId, accessToken);
|
||||
}
|
||||
// 判断系统里是否有这个手机号的用户
|
||||
SysUser sysUser = sysUserService.getUserByPhone(appUser.getMobile());
|
||||
if (sysUser != null) {
|
||||
thirdAccount.setAvatar(appUser.getAvatar());
|
||||
thirdAccount.setRealname(appUser.getName());
|
||||
thirdAccount.setThirdUserId(appUser.getUserid());
|
||||
thirdAccount.setThirdUserUuid(appUser.getUserid());
|
||||
thirdAccount.setSysUserId(sysUser.getId());
|
||||
sysThirdAccountService.updateById(thirdAccount);
|
||||
return sysUser;
|
||||
} else {
|
||||
// 没有就走创建逻辑
|
||||
return sysThirdAccountService.createUser(appUser.getMobile(), appUser.getUserid());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package org.jeecg.modules.system.util;
|
||||
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @Description: 工具类XSSUtils,现在的做法是替换成空字符,CSDN的是进行转义,比如文字开头的"<"转成<
|
||||
* @author: lsq
|
||||
* @date: 2021年07月26日 19:13
|
||||
*/
|
||||
public class XSSUtils {
|
||||
public static String striptXSS(String value) {
|
||||
if (value != null) {
|
||||
value = value.replaceAll(" ", "");
|
||||
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||
value = scriptPattern.matcher(value).replaceAll("");
|
||||
}
|
||||
return HtmlUtils.htmlEscape(value);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String s = striptXSS("<img src=x onload=alert(111).*?><script></script>javascript:eval()\\\\.");
|
||||
System.err.println("s======>" + s);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.jeecg.modules.system.vo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
*
|
||||
* @Author: chenli
|
||||
* @Date: 2020-06-07
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Data
|
||||
public class SysUserOnlineVO {
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 会话编号
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String realname;
|
||||
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 生日
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date birthday;
|
||||
|
||||
/**
|
||||
* 性别(1:男 2:女)
|
||||
*/
|
||||
@Dict(dicCode = "sex")
|
||||
private Integer sex;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String phone;
|
||||
}
|
|
@ -39,7 +39,7 @@ spring:
|
|||
quartz:
|
||||
job-store-type: jdbc
|
||||
initialize-schema: embedded
|
||||
#设置自动启动,默认为 true
|
||||
#定时任务启动开关,true-开 false-关
|
||||
auto-startup: true
|
||||
#启动时更新己存在的Job
|
||||
overwrite-existing-jobs: true
|
||||
|
@ -118,7 +118,7 @@ spring:
|
|||
timeBetweenEvictionRunsMillis: 60000
|
||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
validationQuery: SELECT 1
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
|
@ -131,7 +131,7 @@ spring:
|
|||
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
|
||||
datasource:
|
||||
master:
|
||||
url: jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||
url: jdbc:mysql://127.0.0.1:3306/jeecg-boot-os-re?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: root
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
|
@ -176,8 +176,10 @@ minidao :
|
|||
#DB类型(mysql | postgresql | oracle | sqlserver| other)
|
||||
db-type: mysql
|
||||
jeecg :
|
||||
# 签名密钥串(前后端要一致,正式发布请自行修改)
|
||||
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
|
||||
# 本地:local\Minio:minio\阿里云:alioss
|
||||
uploadType: local
|
||||
uploadType: minio
|
||||
path :
|
||||
#文件上传根目录 设置
|
||||
upload: /opt/upFiles
|
||||
|
@ -190,7 +192,7 @@ jeecg :
|
|||
accessKey: ??
|
||||
secretKey: ??
|
||||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
bucketName: ??
|
||||
bucketName: jeecgdev
|
||||
# ElasticSearch 6设置
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
|
@ -238,12 +240,12 @@ jeecg :
|
|||
port: 30007
|
||||
logPath: logs/jeecg/job/jobhandler/
|
||||
logRetentionDays: 30
|
||||
#自定义路由配置 yml nacos database
|
||||
route:
|
||||
config:
|
||||
data-id: jeecg-gateway-router
|
||||
group: DEFAULT_GROUP
|
||||
data-type: yml
|
||||
#自定义路由配置 yml nacos database
|
||||
data-type: database
|
||||
#分布式锁配置
|
||||
redisson:
|
||||
address: 127.0.0.1:6379
|
||||
|
@ -259,9 +261,12 @@ logging:
|
|||
org.jeecg.modules.system.mapper : info
|
||||
#swagger
|
||||
knife4j:
|
||||
#开启增强配置
|
||||
enable: true
|
||||
#开启生产环境屏蔽
|
||||
production: false
|
||||
basic:
|
||||
enable: true
|
||||
enable: false
|
||||
username: jeecg
|
||||
password: jeecg1314
|
||||
#第三方登录
|
||||
|
|
|
@ -39,7 +39,7 @@ spring:
|
|||
quartz:
|
||||
job-store-type: jdbc
|
||||
initialize-schema: embedded
|
||||
#设置自动启动,默认为 true
|
||||
#定时任务启动开关,true-开 false-关
|
||||
auto-startup: true
|
||||
#启动时更新己存在的Job
|
||||
overwrite-existing-jobs: true
|
||||
|
@ -176,6 +176,8 @@ minidao :
|
|||
#DB类型(mysql | postgresql | oracle | sqlserver| other)
|
||||
db-type: mysql
|
||||
jeecg :
|
||||
# 签名密钥串(前后端要一致,正式发布请自行修改)
|
||||
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
|
||||
# 本地:local\Minio:minio\阿里云:alioss
|
||||
uploadType: alioss
|
||||
path :
|
||||
|
@ -190,12 +192,12 @@ jeecg :
|
|||
accessKey: ??
|
||||
secretKey: ??
|
||||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
bucketName: ??
|
||||
bucketName: jeecgdev
|
||||
staticDomain: https://static.jeecg.com
|
||||
# ElasticSearch 设置
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
cluster-nodes: ??
|
||||
cluster-nodes: 81.70.47.128:9200
|
||||
check-enabled: true
|
||||
# 表单设计器配置
|
||||
desform:
|
||||
|
@ -213,7 +215,7 @@ jeecg :
|
|||
minio_url: http://minio.jeecg.com
|
||||
minio_name: ??
|
||||
minio_pass: ??
|
||||
bucketName: ??
|
||||
bucketName: otatest
|
||||
#大屏报表参数设置
|
||||
jmreport:
|
||||
mode: prod
|
||||
|
@ -239,12 +241,12 @@ jeecg :
|
|||
port: 30007
|
||||
logPath: logs/jeecg/job/jobhandler/
|
||||
logRetentionDays: 30
|
||||
#自定义路由配置 yml nacos database
|
||||
route:
|
||||
config:
|
||||
data-id: jeecg-gateway-router
|
||||
group: DEFAULT_GROUP
|
||||
data-type: yml
|
||||
#自定义路由配置 yml nacos database
|
||||
data-type: database
|
||||
#分布式锁配置
|
||||
redisson:
|
||||
address: 127.0.0.1:6379
|
||||
|
@ -260,7 +262,10 @@ logging:
|
|||
org.jeecg.modules.system.mapper : info
|
||||
#swagger
|
||||
knife4j:
|
||||
production: false
|
||||
#开启增强配置
|
||||
enable: true
|
||||
#开启生产环境屏蔽
|
||||
production: true
|
||||
basic:
|
||||
enable: true
|
||||
username: jeecg
|
||||
|
|
|
@ -39,7 +39,7 @@ spring:
|
|||
quartz:
|
||||
job-store-type: jdbc
|
||||
initialize-schema: embedded
|
||||
#设置自动启动,默认为 true
|
||||
#定时任务启动开关,true-开 false-关
|
||||
auto-startup: true
|
||||
#启动时更新己存在的Job
|
||||
overwrite-existing-jobs: true
|
||||
|
@ -176,6 +176,8 @@ minidao :
|
|||
#DB类型(mysql | postgresql | oracle | sqlserver| other)
|
||||
db-type: mysql
|
||||
jeecg :
|
||||
# 签名密钥串(前后端要一致,正式发布请自行修改)
|
||||
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
|
||||
# 本地:local\Minio:minio\阿里云:alioss
|
||||
uploadType: local
|
||||
path :
|
||||
|
@ -190,12 +192,12 @@ jeecg :
|
|||
accessKey: ??
|
||||
secretKey: ??
|
||||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
bucketName: ??
|
||||
bucketName: jeecgdev
|
||||
staticDomain: https://static.jeecg.com
|
||||
# ElasticSearch 设置
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
cluster-nodes: ??
|
||||
cluster-nodes: 81.70.47.128:9200
|
||||
check-enabled: false
|
||||
# 表单设计器配置
|
||||
desform:
|
||||
|
@ -239,12 +241,12 @@ jeecg :
|
|||
port: 30007
|
||||
logPath: logs/jeecg/job/jobhandler/
|
||||
logRetentionDays: 30
|
||||
#自定义路由配置 yml nacos database
|
||||
route:
|
||||
config:
|
||||
data-id: jeecg-gateway-router
|
||||
group: DEFAULT_GROUP
|
||||
data-type: yml
|
||||
#自定义路由配置 yml nacos database
|
||||
data-type: database
|
||||
#分布式锁配置
|
||||
redisson:
|
||||
address: 127.0.0.1:6379
|
||||
|
@ -260,6 +262,9 @@ cas:
|
|||
prefixUrl: http://cas.example.org:8443/cas
|
||||
#swagger
|
||||
knife4j:
|
||||
#开启增强配置
|
||||
enable: true
|
||||
#开启生产环境屏蔽
|
||||
production: false
|
||||
basic:
|
||||
enable: true
|
||||
|
|
|
@ -9,6 +9,6 @@ ${AnsiColor.BRIGHT_BLUE}
|
|||
|
||||
|
||||
${AnsiColor.BRIGHT_GREEN}
|
||||
Jeecg Boot Version: 2.4.5
|
||||
Jeecg Boot Version: 2.4.6
|
||||
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version}
|
||||
${AnsiColor.BLACK}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class ${entityName} implements Serializable {
|
|||
</#if>
|
||||
/**${po.filedComment}*/
|
||||
<#if po.fieldName == primaryKeyField>
|
||||
@TableId(type = IdType.ID_WORKER_STR)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
<#else>
|
||||
<#if po.fieldDbType =='Date'>
|
||||
<#if po.classType=='date'>
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ${subTab.entityName} implements Serializable {
|
|||
</#if>
|
||||
/**${po.filedComment}*/
|
||||
<#if po.fieldName == primaryKeyField>
|
||||
@TableId(type = IdType.ID_WORKER_STR)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
<#else>
|
||||
<#if po.fieldDbType =='Date'>
|
||||
<#if po.classType=='date'>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.jeecg;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.common.util.security.SecurityTools;
|
||||
import org.jeecg.common.util.security.entity.*;
|
||||
import org.junit.Test;
|
||||
|
@ -30,7 +30,7 @@ public class SecurityToolsTest {
|
|||
// signData为签名数据
|
||||
// data为aes加密数据
|
||||
// asekey为ras加密过的aeskey
|
||||
System.out.println(new JSONObject(sign).toStringPretty());
|
||||
System.out.println(JSONObject.toJSON(sign));
|
||||
|
||||
// 验签解密部分
|
||||
SecurityReq req = new SecurityReq();
|
||||
|
@ -44,6 +44,6 @@ public class SecurityToolsTest {
|
|||
SecurityResp securityResp = SecurityTools.valid(req);
|
||||
//解密报文data为解密报文
|
||||
//sucess 为验签成功失败标志 true代码验签成功,false代表失败
|
||||
System.out.println(new JSONObject(securityResp).toStringPretty());
|
||||
System.out.println(JSONObject.toJSON(securityResp));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-boot-starter</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jeecg-boot-starter-cloud</artifactId>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue