JeecgBoot低代码平台 2.4.5 版本发布,钉钉与企业微信集成版本

pull/2621/head
zhangdaiscott 2021-06-02 15:51:19 +08:00
parent 1bc7ee3345
commit 6840772959
120 changed files with 4734 additions and 239599 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,81 +0,0 @@
-- redissql
INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_route`, `is_leaf`, `keep_alive`, `hidden`, `description`, `status`, `del_flag`, `rule_flag`, `create_by`, `create_time`, `update_by`, `update_time`, `internal_or_external`) VALUES ('1352200630711652354', 'f0675b52d89100ee88472b6800754a08', 'redis', '{{ window._CONFIG[\'domianURL\'] }}/jmreport/view/1352160857479581696', 'layouts/IframePageView', NULL, NULL, '1', NULL, '1', '1.00', '0', '', '1', '1', '0', '0', NULL, '1', '0', '0', 'admin', '2021-01-21 18:25:28', 'admin', '2021-01-22 16:49:43', '0');
--
INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `update_by`, `update_time`, `type`) VALUES ('1356445645198135298', '', 'is_open', '', '0', 'admin', '2021-02-02 11:33:38', 'admin', '2021-02-02 15:28:12', '0');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1356445705549975553', '1356445645198135298', '是', 'Y', '', '1', '1', 'admin', '2021-02-02 11:33:52', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1356445754212290561', '1356445645198135298', '否', 'N', '', '1', '1', 'admin', '2021-02-02 11:34:04', NULL, NULL);
-- author:liusq----date:20210202----for:
--
INSERT INTO `sys_dict`(`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `update_by`, `update_time`, `type`) VALUES ('a7adbcd86c37f7dbc9b66945c82ef9e6', '10', 'yn', '', 0, 'admin', '2019-05-22 19:29:29', NULL, NULL, 0);
INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('51222413e5906cdaf160bb5c86fb827c', 'a7adbcd86c37f7dbc9b66945c82ef9e6', '是', '1', '', 1, 1, 'admin', '2019-05-22 19:29:45', NULL, NULL);
INSERT INTO `sys_dict_item`(`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('c5700a71ad08994d18ad1dacc37a71a9', 'a7adbcd86c37f7dbc9b66945c82ef9e6', '否', '0', '', 1, 1, 'admin', '2019-05-22 19:29:55', NULL, NULL);
-- author:scott----date:20210202----for:
-- 224----
drop table rep_demo_dadong;
drop table rep_demo_daibu;
drop table rep_demo_deliveryorder;
drop table rep_demo_huizong;
drop table rep_demo_income;
drop table rep_demo_jiehsao;
drop table rep_demo_kaoqin;
drop table rep_demo_salesrate;
drop table rep_demo_xiaoshou;
drop table xianlu1_wxtl;
drop table xianlu_wxtl;
drop table yanshi_duozu;
drop table yanshi_jdcx;
drop table yanshi_qipaosandian;
drop table yanshi_sandian;
drop table yanshi_tima;
drop table yanshi_wxtl;
drop table yanshi_yipan;
alter table yanshi_dxtj rename to rep_demo_dxtj;
delete from jimu_report_data_source where report_id in ('1331429368098066432','1333962561053396992','1334028738995818496','1334074491629867008','1337271712059887616','1339478701846433792','1339859143477039104','8e69f5396643b199c92d6f401be4d833');
delete from jimu_report_db where jimu_report_id in('1331429368098066432','1333962561053396992','1334028738995818496','1334074491629867008','1337271712059887616','1339478701846433792','1339859143477039104','8e69f5396643b199c92d6f401be4d833');
delete from jimu_report_db_param where jimu_report_head_id in ('1331429368098066432','1333962561053396992','1334028738995818496','1334074491629867008','1337271712059887616','1339478701846433792','1339859143477039104','8e69f5396643b199c92d6f401be4d833');
delete from jimu_report_db_field where jimu_report_db_id not in (select id from jimu_report_db);
delete from jimu_report where id in ('1331429368098066432','1333962561053396992','1334028738995818496','1334074491629867008','1337271712059887616','1339478701846433792','1339859143477039104','8e69f5396643b199c92d6f401be4d833');
-- JVxeTable
INSERT INTO sys_permission (`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_route`, `is_leaf`, `keep_alive`, `hidden`, `description`, `status`, `del_flag`, `rule_flag`, `create_by`, `create_time`, `update_by`, `update_time`, `internal_or_external`) VALUES ('1365187528377102337', '2a470fc0c3954d9dbb61de6d80846549', 'JVxeTable', '/jeecg/JeecgOrderMainListForJVxeTable', 'jeecg/JeecgOrderMainListForJVxeTable', NULL, NULL, 1, NULL, '1', 2.00, 0, NULL, 1, 1, 0, 0, NULL, '1', 0, 0, 'admin', '2021-02-26 14:30:45', 'admin', '2021-02-26 14:32:05', 0);
--
CREATE TABLE `jimu_report_share` (
`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '',
`report_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '线excelid',
`preview_url` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '',
`preview_lock` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '',
`last_update_time` datetime(0) NULL DEFAULT NULL COMMENT '',
`term_of_validity` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '(0:1:12:7)',
`status` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '(01)',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '';
--
CREATE TABLE `jimu_report_link` (
`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'id',
`report_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'id',
`parameter` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '',
`eject_type` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '0 1 ',
`link_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '',
`api_method` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '0-get,1-post',
`link_type` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '(0 1 2 )',
`api_url` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'api',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '';
update jimu_report_link set link_type = '0';

View File

@ -0,0 +1,62 @@
-- online
ALTER TABLE `onl_auth_relation`
ADD COLUMN `auth_mode` varchar(50) NULL COMMENT 'roledepartuser' AFTER `cgform_id`;
update onl_auth_relation set auth_mode = 'role';
-- qywx_identifier
ALTER TABLE `sys_depart`
ADD COLUMN `qywx_identifier` varchar(100) NULL COMMENT 'ID' AFTER `del_flag`;
-- sys_third_account third_user_id
ALTER TABLE `sys_third_account`
ADD COLUMN `third_user_id` varchar(100) NULL COMMENT 'app' AFTER `third_user_uuid`;
-- APP
INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1387612436586065922', '2a470fc0c3954d9dbb61de6d80846549', 'APP', '/jeecg/ThirdAppMessageTest', 'jeecg/ThirdAppMessageTest', '1', NULL, NULL, '1', NULL, '1', '3', '0', NULL, '1', '0', '0', NULL, 'admin', '2021-04-29 11:39:20', 'admin', '2021-04-29 11:39:27', '0', '0', '1', '0');
--
--
ALTER TABLE `sys_quartz_job`
DROP INDEX `uniq_job_class_name`;
-- []
DELETE FROM `qrtz_cron_triggers`;
DELETE FROM `qrtz_fired_triggers`;
DELETE FROM `qrtz_triggers`;
DELETE FROM `qrtz_job_details`;
UPDATE `sys_quartz_job` SET `status` = '-1';
-- mariaDB issues/I3QID1
update sys_dict_item set item_text = 'MariaDB' where id ='1349250340104474626';
update sys_dict_item set item_text = 'Postgresql' where id ='1349254569766457345';
-- sys_announcementdt_task_id
ALTER TABLE `sys_announcement`
ADD COLUMN `dt_task_id` varchar(100) NULL COMMENT 'task_id' AFTER `msg_abstract`;
--
ALTER TABLE `jimu_report`
MODIFY COLUMN `template` tinyint(1) NULL DEFAULT NULL COMMENT ' 0,1' AFTER `api_code`;
--
ALTER TABLE `jimu_report_db_field`
ADD COLUMN `search_value` varchar(100) NULL COMMENT '' AFTER `dict_code`;
-- jimu_report_dbJSON
ALTER TABLE `jimu_report_db`
ADD COLUMN `json_data` text NULL COMMENT 'jsonjson' AFTER `db_source_type`;
--
ALTER TABLE `jimu_report_data_source`
ADD COLUMN `connect_times` int(1) NULL COMMENT '' AFTER `update_time`;
-- ID
ALTER TABLE `jimu_report_link`
ADD COLUMN `link_chart_id` varchar(50) NULL COMMENT 'ID' AFTER `api_url`;
-- ---
update sys_permission set url="{{ window._CONFIG['domianURL'] }}/jmreport/view/1352160857479581696?token=${token}" where id ='1352200630711652354';
UPDATE `jimu_report_db` SET `jimu_report_id` = '1352160857479581696', `create_by` = 'admin', `update_by` = 'admin', `create_time` = '2021-05-19 19:20:44', `update_time` = '2021-05-19 19:20:44', `db_code` = 'infoForReport', `db_ch_name` = '', `db_type` = '1', `db_table_name` = NULL, `db_dyn_sql` = NULL, `db_key` = NULL, `tb_db_key` = NULL, `tb_db_table_name` = NULL, `java_type` = NULL, `java_value` = NULL, `api_url` = '{{ domainURL }}/sys/actuator/redis/infoForReport', `api_method` = '0', `is_list` = 1, `is_page` = '1', `db_source` = '', `db_source_type` = NULL, `json_data` = NULL WHERE `id` = '60b3feffadc55eb49baa5a48fdf1ff0e';
UPDATE `jimu_report_db` SET `jimu_report_id` = '1352160857479581696', `create_by` = 'admin', `update_by` = 'admin', `create_time` = '2021-05-19 19:20:50', `update_time` = '2021-05-19 19:20:50', `db_code` = 'memoryForReport', `db_ch_name` = '', `db_type` = '1', `db_table_name` = NULL, `db_dyn_sql` = NULL, `db_key` = NULL, `tb_db_key` = NULL, `tb_db_table_name` = NULL, `java_type` = NULL, `java_value` = NULL, `api_url` = '{{ domainURL }}/sys/actuator/redis/memoryForReport', `api_method` = '0', `is_list` = 1, `is_page` = '0', `db_source` = '', `db_source_type` = NULL, `json_data` = NULL WHERE `id` = '6a1d22ca4c95e8fab655d3ceed43a84d';
UPDATE `jimu_report_db` SET `jimu_report_id` = '1352160857479581696', `create_by` = 'admin', `update_by` = 'admin', `create_time` = '2021-05-19 19:21:03', `update_time` = '2021-05-19 19:21:03', `db_code` = 'keysSizeForReport', `db_ch_name` = '', `db_type` = '1', `db_table_name` = NULL, `db_dyn_sql` = NULL, `db_key` = NULL, `tb_db_key` = NULL, `tb_db_table_name` = NULL, `java_type` = NULL, `java_value` = NULL, `api_url` = '{{ domainURL }}/sys/actuator/redis/keysSizeForReport', `api_method` = '0', `is_list` = 1, `is_page` = '0', `db_source` = '', `db_source_type` = NULL, `json_data` = NULL WHERE `id` = 'd4a29dfda94357308faf62be2b94db08';

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.3</version>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.3</version>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.3</version>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base</artifactId>
<version>2.4.3</version>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -114,7 +114,7 @@
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>hibernate-re</artifactId>
<version>2.4.3-RC</version>
<version>2.4.5-RC</version>
</dependency>
<!--mysql-->

View File

@ -0,0 +1,47 @@
package org.jeecg.common.api.desform;
import org.jeecg.common.system.vo.DictModel;
import java.util.List;
import java.util.Map;
/**
* SystemAPI
*
* @author sunjianlei
*/
public interface ISysTranslateAPI {
/**
*
*/
List<String> categoryLoadDictItem(String ids);
/**
* codetext
*
* @param dictCode tableName,text,code
* @param keys key
* @return
*/
List<String> dictLoadDictItem(String dictCode, String keys);
/**
*
*
* @param dictCode tableName,text,code
* @param dictCode key
* @return
*/
List<DictModel> dictGetDictItems(String dictCode);
/**
* JSearchSelectTag
*
*
* @param dictCode codetable,text,code
* @return
*/
List<DictModel> dictLoadDict(String dictCode, String keyword, Integer pageSize);
}

View File

@ -23,6 +23,11 @@ public class MessageDTO implements Serializable {
*/
protected String toUser;
/**
*
*/
protected boolean toAll;
/**
*
*/

View File

@ -1,12 +1,12 @@
package org.jeecg.common.api.vo;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.jeecg.common.constant.CommonConstant;
import lombok.Data;
import org.jeecg.common.constant.CommonConstant;
import java.io.Serializable;
/**
*
@ -112,7 +112,16 @@ public class Result<T> implements Serializable {
r.setResult(data);
return r;
}
public static<T> Result<T> error(String msg, T data) {
Result<T> r = new Result<T>();
r.setSuccess(false);
r.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
r.setMessage(msg);
r.setResult(data);
return r;
}
public static Result<Object> error(String msg) {
return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);
}

View File

@ -14,16 +14,15 @@ import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.ModuleType;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.IPUtils;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

View File

@ -17,6 +17,7 @@ import org.jeecg.common.constant.CommonConstant;
import org.jeecg.modules.base.service.BaseCommonService;
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;
@ -38,6 +39,8 @@ public class DictAspect {
@Autowired
private CommonAPI commonAPI;
@Autowired
public RedisTemplate redisTemplate;
// 定义切点Pointcut
@Pointcut("execution(public * org.jeecg.modules..*.*Controller.*(..))")
@ -144,12 +147,33 @@ public class DictAspect {
if (k.trim().length() == 0) {
continue; //跳过循环
}
//update-begin--Author:scott -- Date:20210531 ----for !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
if (!StringUtils.isEmpty(table)){
log.debug("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code);
tmpValue= commonAPI.translateDictFromTable(table,text,code,k.trim());
log.info("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code);
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]",table,text,code,k.trim());
if (redisTemplate.hasKey(keyString)){
try {
tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
} catch (Exception e) {
log.warn(e.getMessage());
}
}else {
tmpValue= commonAPI.translateDictFromTable(table,text,code,k.trim());
}
}else {
tmpValue = commonAPI.translateDict(code, k.trim());
String keyString = String.format("sys:cache:dict::%s:%s",code,k.trim());
if (redisTemplate.hasKey(keyString)){
try {
tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
} catch (Exception e) {
log.warn(e.getMessage());
}
}else {
tmpValue = commonAPI.translateDict(code, k.trim());
}
}
//update-end--Author:scott -- Date:20210531 ----for !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
if (tmpValue != null) {
if (!"".equals(textValue.toString())) {
textValue.append(",");

View File

@ -305,4 +305,21 @@ public interface CommonConstant {
* /
*/
public final static String THIRD_LOGIN_CODE = "third_login_code";
/**
* APP --> APP
*/
String THIRD_SYNC_TO_APP = "SYNC_TO_APP";
/**
* APPAPP -->
*/
String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL";
/** 系统通告消息状态0=未发布 */
String ANNOUNCEMENT_SEND_STATUS_0 = "0";
/** 系统通告消息状态1=已发布 */
String ANNOUNCEMENT_SEND_STATUS_1 = "1";
/** 系统通告消息状态2=已撤销 */
String ANNOUNCEMENT_SEND_STATUS_2 = "2";
}

View File

@ -9,12 +9,14 @@ public interface DataBaseConstant {
public static final String DB_TYPE_DM = "DM";//达梦数据库
public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
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";
//*********系统上下文变量****************************************
/**
* -
@ -65,6 +67,10 @@ public interface DataBaseConstant {
* "yyyy-MM-dd HH:mm"
*/
public static final String SYS_TIME_TABLE = "sys_time";
/**
* -
*/
public static final String SYS_BASE_PATH = "sys_base_path";
//*********系统上下文变量****************************************

View File

@ -221,20 +221,31 @@ public class QueryGenerator {
if(parameterMap!=null&& parameterMap.containsKey(ORDER_TYPE)) {
order = parameterMap.get(ORDER_TYPE)[0];
}
log.debug("排序规则>>列:"+column+",排序方式:"+order);
log.info("排序规则>>列:" + column + ",排序方式:" + order);
if (oConvertUtils.isNotEmpty(column) && oConvertUtils.isNotEmpty(order)) {
//字典字段,去掉字典翻译文本后缀
if(column.endsWith(CommonConstant.DICT_TEXT_SUFFIX)) {
column = column.substring(0, column.lastIndexOf(CommonConstant.DICT_TEXT_SUFFIX));
}
//SQL注入check
SqlInjectionUtil.filterContent(column);
SqlInjectionUtil.filterContent(column);
//update-begin--Author:scott Date:20210531 for36 多条件排序无效问题修正-------
// 排序规则修改
// 将现有排序 _ 前端传递排序条件{....,column: 'column1,column2',order: 'desc'} 翻译成sql "column1,column2 desc"
// 修改为 _ 前端传递排序条件{....,column: 'column1,column2',order: 'desc'} 翻译成sql "column1 desc,column2 desc"
if (order.toUpperCase().indexOf(ORDER_TYPE_ASC)>=0) {
queryWrapper.orderByAsc(oConvertUtils.camelToUnderline(column));
String columnStr = oConvertUtils.camelToUnderline(column);
String[] columnArray = columnStr.split(",");
queryWrapper.orderByAsc(columnArray);
} else {
queryWrapper.orderByDesc(oConvertUtils.camelToUnderline(column));
String columnStr = oConvertUtils.camelToUnderline(column);
String[] columnArray = columnStr.split(",");
queryWrapper.orderByDesc(columnArray);
}
//update-end--Author:scott Date:20210531 for36 多条件排序无效问题修正-------
}
}
@ -1073,7 +1084,7 @@ public class QueryGenerator {
* @Return: java.lang.String
*/
private static String specialStrConvert(String value) {
if (DataBaseConstant.DB_TYPE_MYSQL.equals(getDbType())) {
if (DataBaseConstant.DB_TYPE_MYSQL.equals(getDbType()) || DataBaseConstant.DB_TYPE_MARIADB.equals(getDbType())) {
String[] special_str = QueryGenerator.LIKE_MYSQL_SPECIAL_STRS.split(",");
for (String str : special_str) {
if (value.indexOf(str) !=-1) {

View File

@ -6,6 +6,11 @@ import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.google.common.base.Joiner;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
@ -16,10 +21,6 @@ import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
/**
* @Author Scott
* @Date 2018-07-12 14:23

View File

@ -14,6 +14,7 @@ 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.sql.Connection;
import java.sql.DatabaseMetaData;
@ -74,7 +75,8 @@ public class CommonUtils {
fileName = fileName.substring(pos + 1);
}
//替换上传文件名字的特殊字符
fileName = fileName.replace("=","").replace(",","").replace("&","").replace("#", "");
fileName = fileName.replace("=","").replace(",","").replace("&","")
.replace("#", "").replace("“", "").replace("”", "");
//替换上传文件名字中的空格
fileName=fileName.replaceAll("\\s","");
return fileName;
@ -106,6 +108,44 @@ public class CommonUtils {
}
return url;
}
/**
*
* @param mf
* @param bizPath
* @return
*/
public static String uploadLocal(MultipartFile mf,String bizPath,String uploadpath){
try {
String fileName = null;
File file = new File(uploadpath + File.separator + bizPath + File.separator );
if (!file.exists()) {
file.mkdirs();// 创建文件根目录
}
String orgName = mf.getOriginalFilename();// 获取文件名
orgName = CommonUtils.getFileName(orgName);
if(orgName.indexOf(".")!=-1){
fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
}else{
fileName = orgName+ "_" + System.currentTimeMillis();
}
String savePath = file.getPath() + File.separator + fileName;
File savefile = new File(savePath);
FileCopyUtils.copy(mf.getBytes(), savefile);
String dbpath = null;
if(oConvertUtils.isNotEmpty(bizPath)){
dbpath = bizPath + File.separator + fileName;
}else{
dbpath = fileName;
}
if (dbpath.contains("\\")) {
dbpath = dbpath.replace("\\", "/");
}
return dbpath;
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return "";
}
/**
*
@ -132,7 +172,7 @@ public class CommonUtils {
return getDatabaseTypeByDataSource(dataSource);
} catch (SQLException e) {
//e.printStackTrace();
log.warn(e.getMessage());
log.warn(e.getMessage(),e);
return "";
}
}
@ -157,8 +197,11 @@ public class CommonUtils {
DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
}else if(dbType.indexOf("postgresql")>=0) {
DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
}else if(dbType.indexOf("mariadb")>=0) {
DB_TYPE = DataBaseConstant.DB_TYPE_MARIADB;
}else {
throw new JeecgBootException("数据库类型:["+dbType+"]不识别!");
log.error("数据库类型:[" + dbType + "]不识别!");
//throw new JeecgBootException("数据库类型:["+dbType+"]不识别!");
}
} catch (Exception e) {
log.error(e.getMessage(), e);

View File

@ -75,7 +75,11 @@ public class MinioUtil {
orgName=file.getName();
}
orgName = CommonUtils.getFileName(orgName);
String objectName = bizPath+"/"+orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
String objectName = bizPath+"/"
+( orgName.indexOf(".")==-1
?orgName + "_" + System.currentTimeMillis()
:orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."))
);
// 使用putObject上传一个本地文件到存储桶中。
if(objectName.startsWith("/")){

View File

@ -13,6 +13,7 @@ import java.util.Map;
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";
@ -47,7 +48,7 @@ public class SqlUtils {
*/
public static boolean dbTypeIsMySQL(String dbType) {
return dbTypeIf(dbType, DATABSE_TYPE_MYSQL, DataBaseConstant.DB_TYPE_MYSQL_NUM);
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) {

View File

@ -111,7 +111,9 @@ public class OssBootUtil {
orgName=file.getName();
}
orgName = CommonUtils.getFileName(orgName);
String fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
String fileName = orgName.indexOf(".")==-1
?orgName + "_" + System.currentTimeMillis()
:orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
if (!fileDir.endsWith("/")) {
fileDir = fileDir.concat("/");
}

View File

@ -23,7 +23,7 @@ import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.Collections;
@ -33,7 +33,7 @@ import java.util.List;
* @Author scott
*/
@Configuration
@EnableSwagger2
@EnableSwagger2WebMvc
@EnableKnife4j
@Import(BeanValidatorPluginsConfiguration.class)
public class Swagger2Config implements WebMvcConfigurer {

View File

@ -19,7 +19,7 @@ public class OssConfiguration {
private String accessKeySecret;
@Value("${jeecg.oss.bucketName}")
private String bucketName;
@Value("${jeecg.oss.staticDomain}")
@Value("${jeecg.oss.staticDomain:}")
private String staticDomain;

View File

@ -1,6 +1,7 @@
package org.jeecg.config.shiro;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
@ -110,6 +111,11 @@ 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");
@ -127,7 +133,7 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告
filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块
filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
filterChainDefinitionMap.put("/eoaSocket/**","anon");//我的聊天
//性能监控 TODO 存在安全漏洞泄露TOEKNdurid连接池也有
filterChainDefinitionMap.put("/actuator/**", "anon");
@ -241,8 +247,17 @@ public class ShiroConfig {
RedisClusterManager redisManager = new RedisClusterManager();
Set<HostAndPort> portSet = new HashSet<>();
lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost() , node.getPort())));
JedisCluster jedisCluster = new JedisCluster(portSet);
redisManager.setJedisCluster(jedisCluster);
//update-begin--Author:scott Date:20210531 for修改集群模式下未设置redis密码的bug issues/I3QNIC
if (oConvertUtils.isNotEmpty(lettuceConnectionFactory.getPassword())) {
JedisCluster jedisCluster = new JedisCluster(portSet, 2000, 2000, 5,
lettuceConnectionFactory.getPassword(), new GenericObjectPoolConfig());
redisManager.setPassword(lettuceConnectionFactory.getPassword());
redisManager.setJedisCluster(jedisCluster);
} else {
JedisCluster jedisCluster = new JedisCluster(portSet);
redisManager.setJedisCluster(jedisCluster);
}
//update-end--Author:scott Date:20210531 for修改集群模式下未设置redis密码的bug issues/I3QNIC
manager = redisManager;
}
return manager;

View File

@ -0,0 +1,79 @@
package org.jeecg.config.thirdapp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* App
*/
@Configuration
public class ThirdAppConfig {
/**
*
*/
public final static String DINGTALK = "DINGTALK";
/**
*
*/
public final static String WECHAT_ENTERPRISE = "WECHAT_ENTERPRISE";
/**
* App
*/
@Value("${third-app.enabled:false}")
private boolean enabled;
/**
* WECHAT_ENTERPRISEDINGTALK
*/
@Autowired
private ThirdAppTypeConfig type;
public boolean isEnabled() {
return enabled;
}
public ThirdAppConfig setEnabled(boolean enabled) {
this.enabled = enabled;
return this;
}
/**
*
*/
public ThirdAppTypeItemVo getWechatEnterprise() {
return this.type.getWECHAT_ENTERPRISE();
}
/**
*
*/
public ThirdAppTypeItemVo getDingtalk() {
return this.type.getDINGTALK();
}
/**
*
*/
public boolean isWechatEnterpriseEnabled() {
try {
return this.enabled && this.getWechatEnterprise().isEnabled();
} catch (Exception e) {
return false;
}
}
/**
*
*/
public boolean isDingtalkEnabled() {
try {
return this.enabled && this.getDingtalk().isEnabled();
} catch (Exception e) {
return false;
}
}
}

View File

@ -0,0 +1,26 @@
package org.jeecg.config.thirdapp;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* APP
*
* @author sunjianlei
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "third-app.type")
public class ThirdAppTypeConfig {
/**
*
*/
private ThirdAppTypeItemVo WECHAT_ENTERPRISE;
/**
*
*/
private ThirdAppTypeItemVo DINGTALK;
}

View File

@ -0,0 +1,36 @@
package org.jeecg.config.thirdapp;
import lombok.Data;
/**
* App
*/
@Data
public class ThirdAppTypeItemVo {
/**
*
*/
private boolean enabled;
/**
* Key
*/
private String clientId;
/**
* Secret
*/
private String clientSecret;
/**
* ID
*/
private String agentId;
/**
* Secret
*/
private String agentAppSecret;
public int getAgentIdInt() {
return Integer.parseInt(agentId);
}
}

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base</artifactId>
<version>2.4.3</version>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>公共模块</description>

View File

@ -81,4 +81,14 @@ public interface CacheConstant {
* onlinekey
*/
public static final String ONLINE_FORM = "sys:cache:online:form";
/**
* online
*/
public static final String ONLINE_RP = "sys:cache:online:rp";
/**
* online
*/
public static final String ONLINE_GRAPH = "sys:cache:online:graph";
}

View File

@ -74,10 +74,11 @@ public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
log.info(" --- redis config init --- ");
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =jacksonSerializer();
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = jacksonSerializer();
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
RedisSerializer<?> stringSerializer = new StringRedisSerializer();
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
// key序列化
redisTemplate.setKeySerializer(stringSerializer);
// value序列化
@ -98,10 +99,13 @@ public class RedisConfig extends CachingConfigurerSupport {
*/
@Bean
public CacheManager cacheManager(LettuceConnectionFactory factory) {
// 配置序列化(缓存默认有效期 6小时
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = jacksonSerializer();
// 配置序列化(解决乱码的问题),并且配置缓存默认有效期 6小时
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(6));
RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
//.disableCachingNullValues();
// 以锁写入的方式创建RedisCacheWriter对象
//update-begin-author:taoyan date:20210316 for:注解CacheEvict根据key删除redis支持通配符*
RedisCacheWriter writer = new JeecgRedisCacheWriter(factory, Duration.ofMillis(50L));
@ -111,6 +115,9 @@ public class RedisConfig extends CachingConfigurerSupport {
//RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1));
/* 自定义配置test:demo 的超时时间为 5分钟*/
RedisCacheManager cacheManager = RedisCacheManager.builder(writer).cacheDefaults(redisCacheConfiguration)
.withInitialCacheConfigurations(singletonMap(CacheConstant.SYS_DICT_TABLE_CACHE,
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)).disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))))
.withInitialCacheConfigurations(singletonMap(CacheConstant.TEST_DEMO_CACHE, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5)).disableCachingNullValues()))
.withInitialCacheConfigurations(singletonMap(CacheConstant.PLUGIN_MALL_RANKING, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(24)).disableCachingNullValues()))
.withInitialCacheConfigurations(singletonMap(CacheConstant.PLUGIN_MALL_PAGE_LIST, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(24)).disableCachingNullValues()))

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.3</version>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.3</version>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -10,6 +10,6 @@ WORKDIR /jeecg-boot
EXPOSE 8080
ADD ./target/jeecg-boot-module-system-2.4.3.jar ./
ADD ./target/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.3.jar
CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jeecg-boot-module-system-2.4.5.jar

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>2.4.3</version>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -34,16 +34,21 @@
<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>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-module-demo</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
<!-- 积木报表 -->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>spring-boot-starter-jimureport</artifactId>
<version>1.3.1-beta4</version>
<version>1.3.3-beta</version>
<exclusions>
<exclusion>
<groupId>org.jeecgframework</groupId>

View File

@ -1,18 +1,14 @@
package org.jeecg.modules.quartz.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.ImportExcelUtil;
import org.jeecg.modules.quartz.entity.QuartzJob;
@ -22,28 +18,21 @@ import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @Description: 线
@ -89,10 +78,6 @@ public class QuartzJobController {
//@RequiresRoles("admin")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<?> add(@RequestBody QuartzJob quartzJob) {
List<QuartzJob> list = quartzJobService.findByJobClassName(quartzJob.getJobClassName());
if (list != null && list.size() > 0) {
return Result.error("该定时任务类名已存在");
}
quartzJobService.saveAndScheduleJob(quartzJob);
return Result.ok("创建定时任务成功");
}
@ -155,15 +140,14 @@ public class QuartzJobController {
/**
*
*
* @param jobClassName
* @param id
* @return
*/
//@RequiresRoles("admin")
@GetMapping(value = "/pause")
@ApiOperation(value = "暂停定时任务")
public Result<Object> pauseJob(@RequestParam(name = "jobClassName", required = true) String jobClassName) {
QuartzJob job = null;
job = quartzJobService.getOne(new LambdaQueryWrapper<QuartzJob>().eq(QuartzJob::getJobClassName, jobClassName));
public Result<Object> pauseJob(@RequestParam(name = "id") String id) {
QuartzJob job = quartzJobService.getById(id);
if (job == null) {
return Result.error("定时任务不存在!");
}
@ -174,14 +158,14 @@ public class QuartzJobController {
/**
*
*
* @param jobClassName
* @param id
* @return
*/
//@RequiresRoles("admin")
@GetMapping(value = "/resume")
@ApiOperation(value = "恢复定时任务")
public Result<Object> resumeJob(@RequestParam(name = "jobClassName", required = true) String jobClassName) {
QuartzJob job = quartzJobService.getOne(new LambdaQueryWrapper<QuartzJob>().eq(QuartzJob::getJobClassName, jobClassName));
public Result<Object> resumeJob(@RequestParam(name = "id") String id) {
QuartzJob job = quartzJobService.getById(id);
if (job == null) {
return Result.error("定时任务不存在!");
}

View File

@ -26,7 +26,7 @@ public class SampleParamJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(String.format("welcome %s! Jeecg-Boot 带参数定时任务 SampleParamJob ! 时间:" + DateUtils.now(), this.parameter));
log.info(" Job Execution key"+jobExecutionContext.getJobDetail().getKey());
log.info( String.format("welcome %s! Jeecg-Boot 带参数定时任务 SampleParamJob ! 时间:" + DateUtils.now(), this.parameter));
}
}

View File

@ -1,8 +1,7 @@
package org.jeecg.modules.quartz.service.impl;
import java.util.Date;
import java.util.List;
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.common.util.DateUtils;
@ -13,9 +12,8 @@ import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.List;
/**
* @Description: 线
@ -46,13 +44,16 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
*/
@Override
public boolean saveAndScheduleJob(QuartzJob quartzJob) {
if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
// 定时器添加
this.schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
}
// DB设置修改
quartzJob.setDelFlag(CommonConstant.DEL_FLAG_0);
return this.save(quartzJob);
boolean success = this.save(quartzJob);
if (success) {
if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
// 定时器添加
this.schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
}
}
return success;
}
/**
@ -60,8 +61,8 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
*/
@Override
public boolean resumeJob(QuartzJob quartzJob) {
schedulerDelete(quartzJob.getJobClassName().trim());
schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
schedulerDelete(quartzJob.getId());
schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
quartzJob.setStatus(CommonConstant.STATUS_NORMAL);
return this.updateById(quartzJob);
}
@ -73,10 +74,10 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
@Override
public boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException {
if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
schedulerDelete(quartzJob.getJobClassName().trim());
schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
schedulerDelete(quartzJob.getId());
schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
}else{
scheduler.pauseJob(JobKey.jobKey(quartzJob.getJobClassName().trim()));
scheduler.pauseJob(JobKey.jobKey(quartzJob.getId()));
}
return this.updateById(quartzJob);
}
@ -86,7 +87,7 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
*/
@Override
public boolean deleteAndStopJob(QuartzJob job) {
schedulerDelete(job.getJobClassName().trim());
schedulerDelete(job.getId());
boolean ok = this.removeById(job.getId());
return ok;
}
@ -98,7 +99,9 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
String ymd = DateUtils.date2Str(startDate,DateUtils.yyyymmddhhmmss.get());
String identity = jobName + ymd;
//3秒后执行 只执行一次
startDate.setTime(startDate.getTime()+3000L);
// update-begin--author:sunjianlei ---- date:20210511--- for定时任务立即执行延迟3秒改成0.1秒-------
startDate.setTime(startDate.getTime() + 100L);
// update-end--author:sunjianlei ---- date:20210511--- for定时任务立即执行延迟3秒改成0.1秒-------
// 定义一个Trigger
SimpleTrigger trigger = (SimpleTrigger)TriggerBuilder.newTrigger()
.withIdentity(identity, JOB_TEST_GROUP)
@ -114,31 +117,31 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
@Override
public void pause(QuartzJob quartzJob){
schedulerDelete(quartzJob.getJobClassName().trim());
schedulerDelete(quartzJob.getId());
quartzJob.setStatus(CommonConstant.STATUS_DISABLE);
this.updateById(quartzJob);
}
/**
*
*
*
* @param jobClassName
* @param cronExpression
* @param parameter
*/
private void schedulerAdd(String jobClassName, String cronExpression, String parameter) {
private void schedulerAdd(String id, String jobClassName, String cronExpression, String parameter) {
try {
// 启动调度器
scheduler.start();
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).usingJobData("parameter", parameter).build();
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(id).usingJobData("parameter", parameter).build();
// 表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName).withSchedule(scheduleBuilder).build();
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(id).withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
@ -153,13 +156,13 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
/**
*
*
* @param jobClassName
* @param id
*/
private void schedulerDelete(String jobClassName) {
private void schedulerDelete(String id) {
try {
scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
scheduler.deleteJob(JobKey.jobKey(jobClassName));
scheduler.pauseTrigger(TriggerKey.triggerKey(id));
scheduler.unscheduleJob(TriggerKey.triggerKey(id));
scheduler.deleteJob(JobKey.jobKey(id));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new JeecgBootException("删除定时任务失败");

View File

@ -133,7 +133,7 @@ public class CommonController {
String orgName = mf.getOriginalFilename();// 获取文件名
orgName = CommonUtils.getFileName(orgName);
if(orgName.indexOf(".")!=-1){
fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));
fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
}else{
fileName = orgName+ "_" + System.currentTimeMillis();
}

View File

@ -1,54 +1,54 @@
package org.jeecg.modules.system.controller;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.CommonSendStatus;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.system.entity.SysAnnouncement;
import org.jeecg.modules.system.entity.SysAnnouncementSend;
import org.jeecg.modules.system.service.ISysAnnouncementSendService;
import org.jeecg.modules.system.service.ISysAnnouncementService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeecg.dingtalk.api.core.response.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.CommonSendStatus;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.system.entity.SysAnnouncement;
import org.jeecg.modules.system.entity.SysAnnouncementSend;
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.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.jeecg.common.constant.CommonConstant.ANNOUNCEMENT_SEND_STATUS_1;
/**
* @Title: Controller
@ -67,6 +67,15 @@ public class SysAnnouncementController {
private ISysAnnouncementSendService sysAnnouncementSendService;
@Resource
private WebSocket webSocket;
@Autowired
ThirdAppWechatEnterpriseServiceImpl wechatEnterpriseService;
@Autowired
ThirdAppDingtalkServiceImpl dingtalkService;
@Autowired
private ISysBaseAPI sysBaseAPI;
@Autowired
@Lazy
private RedisUtil redisUtil;
/**
*
@ -242,6 +251,19 @@ public class SysAnnouncementController {
obj.put(WebsocketConst.MSG_TXT, sysAnnouncement.getTitile());
webSocket.sendMessage(userIds, obj.toJSONString());
}
try {
// 同步企业微信、钉钉的消息通知
Response<String> dtResponse = dingtalkService.sendActionCardMessage(sysAnnouncement, true);
wechatEnterpriseService.sendTextCardMessage(sysAnnouncement, true);
if (dtResponse != null && dtResponse.isSuccess()) {
String taskId = dtResponse.getResult();
sysAnnouncement.setDtTaskId(taskId);
sysAnnouncementService.updateById(sysAnnouncement);
}
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
}
}
@ -265,6 +287,13 @@ public class SysAnnouncementController {
boolean ok = sysAnnouncementService.updateById(sysAnnouncement);
if(ok) {
result.success("该系统通知撤销成功");
if (oConvertUtils.isNotEmpty(sysAnnouncement.getDtTaskId())) {
try {
dingtalkService.recallMessage(sysAnnouncement.getDtTaskId());
} catch (Exception e) {
log.error("第三方APP撤回消息失败", e);
}
}
}
}
@ -423,4 +452,33 @@ public class SysAnnouncementController {
}
return result;
}
/**
* APP
* @param modelAndView
* @param id
* @return
*/
@GetMapping("/show/{id}")
public ModelAndView showContent(ModelAndView modelAndView, @PathVariable("id") String id, HttpServletRequest request) {
SysAnnouncement announcement = sysAnnouncementService.getById(id);
if (announcement != null) {
boolean tokenOK = false;
try {
// 验证Token有效性
tokenOK = TokenUtils.verifyToken(request, sysBaseAPI, redisUtil);
} catch (Exception ignored) {
}
// 判断是否传递了Token并且Token有效如果传了就不做查看限制直接返回
// 如果Token无效就做查看限制只能查看已发布的
if (tokenOK || ANNOUNCEMENT_SEND_STATUS_1.equals(announcement.getSendStatus())) {
modelAndView.addObject("data", announcement);
modelAndView.setViewName("announcement/showContent");
return modelAndView;
}
}
modelAndView.setStatus(HttpStatus.NOT_FOUND);
return modelAndView;
}
}

View File

@ -409,10 +409,11 @@ public class SysCategoryController {
* []
*
* @param ids
* @param delNotExist truefalsekeykey
* @return
*/
@RequestMapping(value = "/loadDictItem", method = RequestMethod.GET)
public Result<List<String>> loadDictItem(@RequestParam(name = "ids") String ids) {
public Result<List<String>> loadDictItem(@RequestParam(name = "ids") String ids, @RequestParam(name = "delNotExist", required = false, defaultValue = "true") boolean delNotExist) {
Result<List<String>> result = new Result<>();
// 非空判断
if (StringUtils.isBlank(ids)) {
@ -420,13 +421,8 @@ public class SysCategoryController {
result.setMessage("ids 不能为空");
return result;
}
String[] idArray = ids.split(",");
LambdaQueryWrapper<SysCategory> query = new LambdaQueryWrapper<>();
query.in(SysCategory::getId, Arrays.asList(idArray));
// 查询数据
List<SysCategory> list = this.sysCategoryService.list(query);
// 取出name并返回
List<String> textList = list.stream().map(SysCategory::getName).collect(Collectors.toList());
List<String> textList = sysCategoryService.loadDictItem(ids, delNotExist);
result.setSuccess(true);
result.setResult(textList);
return result;

View File

@ -1,12 +1,9 @@
package org.jeecg.modules.system.controller;
import java.io.IOException;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.jeecg.common.api.vo.Result;
@ -23,28 +20,25 @@ import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.model.DepartIdModel;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysPositionService;
import org.jeecg.modules.system.service.ISysUserDepartService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.util.FindsDepartsChildrenUtil;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
/**
* <p>
@ -132,6 +126,33 @@ public class SysDepartController {
return result;
}
/**
* ID
*
* @param departId departId
* @param orgCode orgCodedepartIdorgCode
*/
@GetMapping("/queryAllParentId")
public Result queryParentIds(
@RequestParam(name = "departId", required = false) String departId,
@RequestParam(name = "orgCode", required = false) String orgCode
) {
try {
JSONObject data;
if (oConvertUtils.isNotEmpty(departId)) {
data = sysDepartService.queryAllParentIdByDepartId(departId);
} else if (oConvertUtils.isNotEmpty(orgCode)) {
data = sysDepartService.queryAllParentIdByOrgCode(orgCode);
} else {
return Result.error("departId 和 orgCode 不能都为空!");
}
return Result.OK(data);
} catch (Exception e) {
log.error(e.getMessage(), e);
return Result.error(e.getMessage());
}
}
/**
* ,
*

View File

@ -31,7 +31,6 @@ import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.result.ExcelImportResult;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -122,44 +121,20 @@ public class SysDictController {
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>>();
List<DictModel> ls = null;
try {
if(dictCode.indexOf(",")!=-1) {
//关联表字典举例sys_user,realname,id
String[] params = dictCode.split(",");
if(params.length<3) {
result.error500("字典Code格式不正确");
return result;
}
//SQL注入校验只限制非法串改数据库
final String[] sqlInjCheck = {params[0],params[1],params[2]};
SqlInjectionUtil.filterContent(sqlInjCheck);
if(params.length==4) {
//SQL注入校验查询条件SQL 特殊check此方法仅供此处使用
SqlInjectionUtil.specialFilterContent(params[3]);
ls = sysDictService.queryTableDictItemsByCodeAndFilter(params[0],params[1],params[2],params[3]);
}else if (params.length==3) {
ls = sysDictService.queryTableDictItemsByCode(params[0],params[1],params[2]);
}else{
result.error500("字典Code格式不正确");
return result;
}
}else {
//字典表
ls = sysDictService.queryDictItemsByCode(dictCode);
List<DictModel> ls = sysDictService.getDictItems(dictCode);
if (ls == null) {
result.error500("字典Code格式不正确");
return result;
}
result.setSuccess(true);
result.setResult(ls);
log.debug(result.toString());
result.setSuccess(true);
result.setResult(ls);
log.debug(result.toString());
} catch (Exception e) {
log.error(e.getMessage(),e);
log.error(e.getMessage(), e);
result.error500("操作失败");
return result;
}
return result;
}
@ -198,8 +173,9 @@ public class SysDictController {
}
/**
* JSearchSelectTag
*
* @param dictCode
* @param dictCode codetable,text,code
* @return
*/
@RequestMapping(value = "/loadDict/{dictCode}", method = RequestMethod.GET)
@ -209,39 +185,75 @@ public class SysDictController {
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
log.info(" 加载字典表数据,加载关键字: "+ keyword);
Result<List<DictModel>> result = new Result<List<DictModel>>();
List<DictModel> ls = null;
try {
if(dictCode.indexOf(",")!=-1) {
String[] params = dictCode.split(",");
if(params.length!=3) {
result.error500("字典Code格式不正确");
return result;
}
if(pageSize!=null){
ls = sysDictService.queryLittleTableDictItems(params[0],params[1],params[2],keyword, pageSize);
}else{
ls = sysDictService.queryTableDictItems(params[0],params[1],params[2],keyword);
}
result.setSuccess(true);
result.setResult(ls);
log.info(result.toString());
}else {
List<DictModel> ls = sysDictService.loadDict(dictCode, keyword, pageSize);
if (ls == null) {
result.error500("字典Code格式不正确");
return result;
}
result.setSuccess(true);
result.setResult(ls);
log.info(result.toString());
return result;
} catch (Exception e) {
log.error(e.getMessage(),e);
result.error500("操作失败");
return result;
}
}
/**
* 使
* @param dictCode
* @param keyword
* @param sign
* @param pageSize
* @return
*/
@RequestMapping(value = "/loadDictOrderByValue/{dictCode}", method = RequestMethod.GET)
public Result<List<DictModel>> loadDictOrderByValue(
@PathVariable String dictCode,
@RequestParam(name = "keyword") String keyword,
@RequestParam(value = "sign", required = false) String sign,
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
// 首次查询查出来用户选中的值,并且不分页
Result<List<DictModel>> firstRes = this.loadDict(dictCode, keyword, sign, null);
if (!firstRes.isSuccess()) {
return firstRes;
}
// 然后再查询出第一页的数据
Result<List<DictModel>> result = this.loadDict(dictCode, "", sign, pageSize);
if (!result.isSuccess()) {
return result;
}
// 合并两次查询的数据
List<DictModel> firstList = firstRes.getResult();
List<DictModel> list = result.getResult();
for (DictModel firstItem : firstList) {
// anyMatch 表示判断的条件里任意一个元素匹配成功返回true
// allMatch 表示判断条件里的元素所有的都匹配成功返回true
// noneMatch 跟 allMatch 相反表示判断条件里的元素所有的都匹配失败返回true
boolean none = list.stream().noneMatch(item -> item.getValue().equals(firstItem.getValue()));
// 当元素不存在时,再添加到集合里
if (none) {
list.add(0, firstItem);
}
}
return result;
}
/**
*
* codetext
* @param dictCode tableName,text,code
* @param keys key
* @param sign
* @param delNotExist truefalsekeykey
* @param request
* @return
*/
@RequestMapping(value = "/loadDictItem/{dictCode}", method = RequestMethod.GET)
public Result<List<String>> loadDictItem(@PathVariable String dictCode,@RequestParam(name="key") String keys, @RequestParam(value = "sign",required = false) String sign,HttpServletRequest request) {
public Result<List<String>> loadDictItem(@PathVariable String dictCode,@RequestParam(name="key") String keys, @RequestParam(value = "sign",required = false) String sign,@RequestParam(value = "delNotExist",required = false,defaultValue = "true") boolean delNotExist,HttpServletRequest request) {
Result<List<String>> result = new Result<>();
try {
if(dictCode.indexOf(",")!=-1) {
@ -250,7 +262,7 @@ public class SysDictController {
result.error500("字典Code格式不正确");
return result;
}
List<String> texts = sysDictService.queryTableDictByKeys(params[0], params[1], params[2], keys);
List<String> texts = sysDictService.queryTableDictByKeys(params[0], params[1], params[2], keys, delNotExist);
result.setSuccess(true);
result.setResult(texts);
@ -407,12 +419,14 @@ public class SysDictController {
//清空字典缓存
Set keys = redisTemplate.keys(CacheConstant.SYS_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 + "*");
Set keys4 = redisTemplate.keys(CacheConstant.SYS_DEPART_IDS_CACHE + "*");
Set keys5 = redisTemplate.keys( "jmreport:cache:dict*");
Set keys6 = redisTemplate.keys( "jmreport:cache:dictTable*");
redisTemplate.delete(keys);
redisTemplate.delete(keys2);
redisTemplate.delete(keys21);
redisTemplate.delete(keys3);
redisTemplate.delete(keys4);
redisTemplate.delete(keys5);

View File

@ -145,8 +145,8 @@ public class SysUserController {
user.setPassword(passwordEncode);
user.setStatus(1);
user.setDelFlag(CommonConstant.DEL_FLAG_0);
sysUserService.addUserWithRole(user, selectedRoles);
sysUserService.addUserWithDepart(user, selectedDeparts);
// 保存用户走一个service 保证事务
sysUserService.saveUser(user, selectedRoles, selectedDeparts);
result.success("添加成功!");
} catch (Exception e) {
log.error(e.getMessage(), e);
@ -172,9 +172,8 @@ public class SysUserController {
user.setPassword(sysUser.getPassword());
String roles = jsonObject.getString("selectedroles");
String departs = jsonObject.getString("selecteddeparts");
sysUserService.editUserWithRole(user, roles);
sysUserService.editUserWithDepart(user, departs);
sysUserService.updateNullPhoneEmail();
// 修改用户走一个service 保证事务
sysUserService.editUser(user, roles, departs);
result.success("修改成功!");
}
} catch (Exception e) {
@ -279,6 +278,7 @@ public class SysUserController {
result.setResult(true);
try {
//通过传入信息查询新的用户信息
sysUser.setPassword(null);
SysUser user = sysUserService.getOne(new QueryWrapper<SysUser>(sysUser));
if (user != null) {
result.setSuccess(false);
@ -298,6 +298,7 @@ public class SysUserController {
/**
*
*/
//@RequiresRoles({"admin"})
@RequestMapping(value = "/changePassword", method = RequestMethod.PUT)
public Result<?> changePassword(@RequestBody SysUser sysUser) {
SysUser u = this.sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, sysUser.getUsername()));
@ -388,6 +389,23 @@ public class SysUserController {
}
}
/**
*
* @param departId
* @param username
* @return
*/
@RequestMapping(value = "/queryUserComponentData", method = RequestMethod.GET)
public Result<IPage<SysUser>> queryUserComponentData(
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
@RequestParam(name = "departId", required = false) String departId,
@RequestParam(name="realname",required=false) String realname,
@RequestParam(name="username",required=false) String username) {
IPage<SysUser> pageList = sysUserDepartService.queryDepartUserPageList(departId, username, realname, pageSize, pageNo);
return Result.OK(pageList);
}
/**
* excel
*
@ -521,13 +539,17 @@ public class SysUserController {
/**
*
*/
//@RequiresRoles({"admin"})
@RequestMapping(value = "/updatePassword", method = RequestMethod.PUT)
public Result<?> changPassword(@RequestBody JSONObject json) {
//@RequiresRoles({"admin"})
@RequestMapping(value = "/updatePassword", method = RequestMethod.PUT)
public Result<?> updatePassword(@RequestBody JSONObject json) {
String username = json.getString("username");
String oldpassword = json.getString("oldpassword");
String password = json.getString("password");
String confirmpassword = json.getString("confirmpassword");
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
if(!sysUser.getUsername().equals(username)){
return Result.error("只允许修改自己的密码!");
}
SysUser user = this.sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
if(user==null) {
return Result.error("用户不存在!");
@ -1338,4 +1360,6 @@ public class SysUserController {
sysUserService.updateById(user);
return Result.ok("手机号设置成功!");
}
}

View File

@ -0,0 +1,261 @@
package org.jeecg.modules.system.controller;
import com.alibaba.fastjson.JSONObject;
import com.jeecg.dingtalk.api.core.response.Response;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.config.thirdapp.ThirdAppConfig;
import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl;
import org.jeecg.modules.system.service.impl.ThirdAppWechatEnterpriseServiceImpl;
import org.jeecg.modules.system.vo.thirdapp.SyncInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* App
*/
@Slf4j
@RestController("thirdAppController")
@RequestMapping("/sys/thirdApp")
public class ThirdAppController {
@Autowired
ThirdAppConfig thirdAppConfig;
@Autowired
ThirdAppWechatEnterpriseServiceImpl wechatEnterpriseService;
@Autowired
ThirdAppDingtalkServiceImpl dingtalkService;
/**
*
*/
@GetMapping("/getEnabledType")
public Result getEnabledType() {
Map<String, Boolean> enabledMap = new HashMap<>();
enabledMap.put("wechatEnterprise", thirdAppConfig.isWechatEnterpriseEnabled());
enabledMap.put("dingtalk", thirdAppConfig.isDingtalkEnabled());
return Result.OK(enabledMap);
}
/**
* []
*
* @param ids
* @return
*/
@GetMapping("/sync/wechatEnterprise/user/toApp")
public Result syncWechatEnterpriseUserToApp(@RequestParam(value = "ids", required = false) String ids) {
if (thirdAppConfig.isWechatEnterpriseEnabled()) {
SyncInfoVo syncInfo = wechatEnterpriseService.syncLocalUserToThirdApp(ids);
if (syncInfo.getFailInfo().size() == 0) {
return Result.OK("同步成功", syncInfo);
} else {
return Result.error("同步失败", syncInfo);
}
}
return Result.error("企业微信同步功能已禁用");
}
/**
* []
*
* @param ids
* @return
*/
@GetMapping("/sync/wechatEnterprise/user/toLocal")
public Result syncWechatEnterpriseUserToLocal(@RequestParam(value = "ids", required = false) String ids) {
if (thirdAppConfig.isWechatEnterpriseEnabled()) {
SyncInfoVo syncInfo = wechatEnterpriseService.syncThirdAppUserToLocal();
if (syncInfo.getFailInfo().size() == 0) {
return Result.OK("同步成功", syncInfo);
} else {
return Result.error("同步失败", syncInfo);
}
}
return Result.error("企业微信同步功能已禁用");
}
/**
* []
*
* @param ids
* @return
*/
@GetMapping("/sync/wechatEnterprise/depart/toApp")
public Result syncWechatEnterpriseDepartToApp(@RequestParam(value = "ids", required = false) String ids) {
if (thirdAppConfig.isWechatEnterpriseEnabled()) {
boolean flag = wechatEnterpriseService.syncLocalDepartmentToThirdApp(ids);
return flag ? Result.OK("同步成功", null) : Result.error("同步失败");
}
return Result.error("企业微信同步功能已禁用");
}
/**
* []
*
* @param ids
* @return
*/
@GetMapping("/sync/wechatEnterprise/depart/toLocal")
public Result syncWechatEnterpriseDepartToLocal(@RequestParam(value = "ids", required = false) String ids) {
if (thirdAppConfig.isWechatEnterpriseEnabled()) {
SyncInfoVo syncInfo = wechatEnterpriseService.syncThirdAppDepartmentToLocal(ids);
if (syncInfo.getFailInfo().size() == 0) {
return Result.OK("同步成功", syncInfo);
} else {
return Result.error("同步失败", syncInfo);
}
}
return Result.error("企业微信同步功能已禁用");
}
/**
* []
*
* @param ids
* @return
*/
@GetMapping("/sync/dingtalk/depart/toApp")
public Result syncDingtalkDepartToApp(@RequestParam(value = "ids", required = false) String ids) {
if (thirdAppConfig.isDingtalkEnabled()) {
boolean flag = dingtalkService.syncLocalDepartmentToThirdApp(ids);
return flag ? Result.OK("同步成功", null) : Result.error("同步失败");
}
return Result.error("钉钉同步功能已禁用");
}
/**
* []
*
* @param ids
* @return
*/
@GetMapping("/sync/dingtalk/depart/toLocal")
public Result syncDingtalkDepartToLocal(@RequestParam(value = "ids", required = false) String ids) {
if (thirdAppConfig.isDingtalkEnabled()) {
SyncInfoVo syncInfo = dingtalkService.syncThirdAppDepartmentToLocal(ids);
if (syncInfo.getFailInfo().size() == 0) {
return Result.OK("同步成功", syncInfo);
} else {
return Result.error("同步失败", syncInfo);
}
}
return Result.error("钉钉同步功能已禁用");
}
/**
* []
*
* @param ids
* @return
*/
@GetMapping("/sync/dingtalk/user/toApp")
public Result syncDingtalkUserToApp(@RequestParam(value = "ids", required = false) String ids) {
if (thirdAppConfig.isDingtalkEnabled()) {
SyncInfoVo syncInfo = dingtalkService.syncLocalUserToThirdApp(ids);
if (syncInfo.getFailInfo().size() == 0) {
return Result.OK("同步成功", syncInfo);
} else {
return Result.error("同步失败", syncInfo);
}
}
return Result.error("钉钉同步功能已禁用");
}
/**
* []
*
* @param ids
* @return
*/
@GetMapping("/sync/dingtalk/user/toLocal")
public Result syncDingtalkUserToLocal(@RequestParam(value = "ids", required = false) String ids) {
if (thirdAppConfig.isDingtalkEnabled()) {
SyncInfoVo syncInfo = dingtalkService.syncThirdAppUserToLocal();
if (syncInfo.getFailInfo().size() == 0) {
return Result.OK("同步成功", syncInfo);
} else {
return Result.error("同步失败", syncInfo);
}
}
return Result.error("钉钉同步功能已禁用");
}
/**
*
*
* @return
*/
@PostMapping("/sendMessageTest")
public Result sendMessageTest(@RequestBody JSONObject params, HttpServletRequest request) {
/* 获取前台传递的参数 */
// 第三方app的类型
String app = params.getString("app");
// 是否发送给全部人
boolean sendAll = params.getBooleanValue("sendAll");
// 消息接收者传sys_user表的username字段多个用逗号分割
String receiver = params.getString("receiver");
// 消息内容
String content = params.getString("content");
String fromUser = JwtUtil.getUserNameByToken(request);
String title = "第三方APP消息测试";
MessageDTO message = new MessageDTO(fromUser, receiver, title, content);
message.setToAll(sendAll);
if (ThirdAppConfig.WECHAT_ENTERPRISE.equals(app)) {
if (thirdAppConfig.isWechatEnterpriseEnabled()) {
JSONObject response = wechatEnterpriseService.sendMessageResponse(message, false);
return Result.OK(response);
}
return Result.error("企业微信已被禁用");
} else if (ThirdAppConfig.DINGTALK.equals(app)) {
if (thirdAppConfig.isDingtalkEnabled()) {
Response<String> response = dingtalkService.sendMessageResponse(message, false);
return Result.OK(response);
}
return Result.error("钉钉已被禁用");
}
return Result.error("不识别的第三方APP");
}
/**
*
*
* @return
*/
@PostMapping("/recallMessageTest")
public Result recallMessageTest(@RequestBody JSONObject params) {
/* 获取前台传递的参数 */
// 第三方app的类型
String app = params.getString("app");
// 消息id
String msg_task_id = params.getString("msg_task_id");
if (ThirdAppConfig.WECHAT_ENTERPRISE.equals(app)) {
if (thirdAppConfig.isWechatEnterpriseEnabled()) {
return Result.error("企业微信不支持撤回消息");
}
return Result.error("企业微信已被禁用");
} else if (ThirdAppConfig.DINGTALK.equals(app)) {
if (thirdAppConfig.isDingtalkEnabled()) {
Response<JSONObject> response = dingtalkService.recallMessageResponse(msg_task_id);
if (response.isSuccess()) {
return Result.OK("撤回成功", response);
} else {
return Result.error("撤回失败:" + response.getErrcode() + "——" + response.getErrmsg(), response);
}
}
return Result.error("钉钉已被禁用");
}
return Result.error("不识别的第三方APP");
}
}

View File

@ -1,17 +1,16 @@
package org.jeecg.modules.system.entity;
import java.io.Serializable;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
/**
* @Description:
* @Author: jeecg-boot
@ -144,4 +143,8 @@ public class SysAnnouncement implements Serializable {
*
*/
private java.lang.String msgAbstract;
/**
* task_id
*/
private java.lang.String dtTaskId;
}

View File

@ -6,13 +6,11 @@ import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
@ -73,6 +71,8 @@ public class SysDepart implements Serializable {
/**删除状态0正常1已删除*/
@Dict(dicCode = "del_flag")
private String delFlag;
/**对接企业微信的ID*/
private String qywxIdentifier;
/**创建人*/
private String createBy;
/**创建日期*/

View File

@ -1,18 +1,13 @@
package org.jeecg.modules.system.entity;
import java.io.Serializable;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
/**
@ -60,4 +55,8 @@ public class SysThirdAccount {
@Excel(name = "真实姓名", width = 15)
@ApiModelProperty(value = "真实姓名")
private java.lang.String thirdUserUuid;
/**真实姓名*/
@Excel(name = "第三方用户账号", width = 15)
@ApiModelProperty(value = "第三方用户账号")
private java.lang.String thirdUserId;
}

View File

@ -6,7 +6,6 @@ import java.util.Map;
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.ResultType;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.jeecg.common.system.vo.DictModel;
@ -132,4 +131,26 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
*/
@Deprecated
public Page<DictModel> queryDictTablePageList(Page page, @Param("query") DictQuery query);
/**
*
* @param page
* @param table
* @param text
* @param code
* @param filterSql
* @return
*/
IPage<DictModel> queryTableDictWithFilter(Page<DictModel> page, @Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql);
/**
*
* @param table
* @param text
* @param code
* @param filterSql
* @return
*/
List<DictModel> queryAllTableDictItems(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql);
}

View File

@ -1,17 +1,26 @@
package org.jeecg.modules.system.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.system.entity.SysThirdAccount;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2020-11-17
* @Date: 2020-11-17
* @Version: V1.0
*/
public interface SysThirdAccountMapper extends BaseMapper<SysThirdAccount> {
/**
* sysUsername
*
* @param sysUsernameArr username
* @param thirdType
* @return
*/
List<SysThirdAccount> selectThirdIdsByUsername(@Param("sysUsernameArr") String[] sysUsernameArr, @Param("thirdType") String thirdType);
}

View File

@ -1,11 +1,32 @@
package org.jeecg.modules.system.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.entity.SysUserDepart;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface SysUserDepartMapper extends BaseMapper<SysUserDepart>{
List<SysUserDepart> getUserDepartByUid(@Param("userId") String userId);
/**
*
* @param orgCode
* @param realname
* @return
*/
List<SysUser> queryDepartUserList(@Param("orgCode") String orgCode, @Param("realname") String realname);
/**
*
* @param page
* @param orgCode
* @param username
* @param realname
* @return
*/
IPage<SysUser> queryDepartUserPageList(Page<SysUser> page, @Param("orgCode") String orgCode, @Param("username") String username, @Param("realname") String realname);
}

View File

@ -106,4 +106,22 @@
</if>
</select>
<!--通过查询指定table的 text code 获取字典数据,且支持关键字和自定义查询条件查询 分页-->
<select id="queryTableDictWithFilter" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text", ${code} as "value" from ${table}
<if test="filterSql != null and filterSql != ''">
${filterSql}
</if>
</select>
<!--通过查询指定table的 text code 获取字典数据,且支持关键字和自定义查询条件查询 获取所有 -->
<select id="queryAllTableDictItems" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text", ${code} as "value" from ${table}
<if test="filterSql != null and filterSql != ''">
${filterSql}
</if>
</select>
</mapper>

View File

@ -24,7 +24,7 @@
<!-- 首页访问统计 -->
<select id="findVisitCount" resultType="java.util.HashMap">
<if test="dbType == 'MYSQL'">
<if test="dbType == 'MYSQL' || dbType == 'MARIADB'">
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'">
<if test="dbType == 'ORACLE' || dbType == 'DM'">
select count(*) as visit
,count(distinct(ip)) as ip
,to_char(create_time, 'yyyy-mm-dd') as tian

View File

@ -2,4 +2,13 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.system.mapper.SysThirdAccountMapper">
<!-- 通过 sysUsername 集合批量查询 -->
<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
<!-- TODO in 查询数据量大的时候可能会报错 -->
<foreach collection="sysUsernameArr" item="item" open=" sys_user.username IN (" close=")" separator=",">#{item}</foreach>
</select>
</mapper>

View File

@ -6,4 +6,29 @@
FROM sys_user_depart
WHERE user_id = #{userId, jdbcType=VARCHAR}
</select>
<!-- 查询指定部门下的用户 并且支持用户账号模糊查询 -->
<select id="queryDepartUserList" resultType="org.jeecg.modules.system.entity.SysUser">
select a.* from sys_user a
join sys_user_depart b on b.user_id = a.id
join sys_depart c on b.dep_id = c.id
where a.del_flag = 0 and c.org_code like '${orgCode}%'
<if test="realname!=null and realname!=''">
and a.realname like '%${realname}%'
</if>
</select>
<!-- 根据部门查询部门用户 分页 -->
<select id="queryDepartUserPageList" resultType="org.jeecg.modules.system.entity.SysUser">
select a.*, c.depart_name as org_code_txt from sys_user a
join sys_user_depart b on b.user_id = a.id
join sys_depart c on b.dep_id = c.id
where a.del_flag = 0 and c.org_code like '${orgCode}%'
<if test="username!=null and username!=''">
and a.username like '%${username}%'
</if>
<if test="realname!=null and realname!=''">
and a.realname like '%${realname}%'
</if>
</select>
</mapper>

View File

@ -65,6 +65,8 @@ public class SysDepartTreeModel implements Serializable{
private String delFlag;
private String qywxIdentifier;
private String createBy;
private Date createTime;
@ -100,6 +102,7 @@ public class SysDepartTreeModel implements Serializable{
this.memo = sysDepart.getMemo();
this.status = sysDepart.getStatus();
this.delFlag = sysDepart.getDelFlag();
this.qywxIdentifier = sysDepart.getQywxIdentifier();
this.createBy = sysDepart.getCreateBy();
this.createTime = sysDepart.getCreateTime();
this.updateBy = sysDepart.getUpdateBy();
@ -287,6 +290,14 @@ public class SysDepartTreeModel implements Serializable{
this.delFlag = delFlag;
}
public String getQywxIdentifier() {
return qywxIdentifier;
}
public void setQywxIdentifier(String qywxIdentifier) {
this.qywxIdentifier = qywxIdentifier;
}
public String getCreateBy() {
return createBy;
}
@ -349,6 +360,7 @@ public class SysDepartTreeModel implements Serializable{
Objects.equals(memo, model.memo) &&
Objects.equals(status, model.status) &&
Objects.equals(delFlag, model.delFlag) &&
Objects.equals(qywxIdentifier, model.qywxIdentifier) &&
Objects.equals(createBy, model.createBy) &&
Objects.equals(createTime, model.createTime) &&
Objects.equals(updateBy, model.updateBy) &&
@ -364,7 +376,7 @@ public class SysDepartTreeModel implements Serializable{
return Objects.hash(id, parentId, departName, departNameEn, departNameAbbr,
departOrder, description, orgCategory, orgType, orgCode, mobile, fax, address,
memo, status, delFlag, createBy, createTime, updateBy, updateTime,
memo, status, delFlag, qywxIdentifier, createBy, createTime, updateBy, updateTime,
children);
}

View File

@ -1,13 +1,12 @@
package org.jeecg.modules.system.service;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.system.entity.SysCategory;
import org.jeecg.modules.system.model.TreeSelectModel;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* @Description:
@ -58,5 +57,22 @@ public interface ISysCategoryService extends IService<SysCategory> {
* @param ids
*/
void deleteSysCategory(String ids);
/**
* []
*
* @param ids
* @return
*/
List<String> loadDictItem(String ids);
/**
* []
*
* @param ids
* @param delNotExist falsekeykey
* @return
*/
List<String> loadDictItem(String ids, boolean delNotExist);
}

View File

@ -1,5 +1,6 @@
package org.jeecg.modules.system.service;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.model.DepartIdModel;
@ -112,6 +113,20 @@ public interface ISysDepartService extends IService<SysDepart>{
* @return
*/
List<SysDepartTreeModel> queryTreeListByPid(String parentId);
/**
* ID
*
* @param departId departId
*/
JSONObject queryAllParentIdByDepartId(String departId);
/**
* ID
*
* @param orgCode orgCode
*/
JSONObject queryAllParentIdByOrgCode(String orgCode);
/**
*
* @return

View File

@ -1,15 +1,15 @@
package org.jeecg.modules.system.service;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.system.vo.DictQuery;
import org.jeecg.modules.system.entity.SysDict;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.system.entity.SysDictItem;
import org.jeecg.modules.system.model.TreeSelectModel;
import java.util.List;
import java.util.Map;
/**
* <p>
*
@ -37,6 +37,8 @@ public interface ISysDictService extends IService<SysDict> {
@Deprecated
List<String> queryTableDictByKeys(String table, String text, String code, String keys);
@Deprecated
List<String> queryTableDictByKeys(String table, String text, String code, String keys,boolean delNotExist);
/**
*
@ -50,19 +52,19 @@ public interface ISysDictService extends IService<SysDict> {
*
*/
public Integer saveMain(SysDict sysDict, List<SysDictItem> sysDictItemList);
/**
* id -->value,departName -->text
* @return
*/
public List<DictModel> queryAllDepartBackDictModel();
/**
* username -->value,realname -->text
* @return
*/
public List<DictModel> queryAllUserBackDictModel();
/**
*
* @param table
@ -82,7 +84,18 @@ public interface ISysDictService extends IService<SysDict> {
* @param keyword
* @return
*/
public List<DictModel> queryLittleTableDictItems(String table, String text, String code,String keyword, int pageSize);
public List<DictModel> queryLittleTableDictItems(String table, String text, String code, String condition, String keyword, int pageSize);
/**
*
* @param table
* @param text
* @param code
* @param condition
* @param keyword
* @return
*/
public List<DictModel> queryAllTableDictItems(String table, String text, String code, String condition, String keyword);
/**
*
* @param table
@ -125,4 +138,21 @@ public interface ISysDictService extends IService<SysDict> {
@Deprecated
public List<DictModel> queryDictTablePageList(DictQuery query,int pageSize, int pageNo);
/**
*
* @param dictCode code
* @param dictCode ,,code | sys_user,realname,id
* @return
*/
List<DictModel> getDictItems(String dictCode);
/**
* JSearchSelectTag
*
*
* @param dictCode codetable,text,code
* @return
*/
List<DictModel> loadDict(String dictCode, String keyword, Integer pageSize);
}

View File

@ -11,4 +11,9 @@ import org.jeecg.modules.system.entity.SysPosition;
*/
public interface ISysPositionService extends IService<SysPosition> {
/**
* code
*/
SysPosition getByCode(String code);
}

View File

@ -1,9 +1,11 @@
package org.jeecg.modules.system.service;
import org.jeecg.modules.system.entity.SysThirdAccount;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.system.entity.SysThirdAccount;
import org.jeecg.modules.system.entity.SysUser;
import java.util.List;
/**
* @Description:
* @Author: jeecg-boot
@ -15,5 +17,19 @@ public interface ISysThirdAccountService extends IService<SysThirdAccount> {
void updateThirdUserId(SysUser sysUser,String thirdUserUuid);
/**创建第三方用户*/
SysUser createUser(String phone, String thirdUserUuid);
/** 根据本地userId查询数据 */
SysThirdAccount getOneBySysUserId(String sysUserId, String thirdType);
/** 根据第三方userId查询数据 */
SysThirdAccount getOneByThirdUserId(String thirdUserId, String thirdType);
/**
* sysUsername
*
* @param sysUsernameArr username
* @param thirdType
* @return
*/
List<SysThirdAccount> listThirdUserIdByUsername(String[] sysUsernameArr, String thirdType);
}

View File

@ -3,6 +3,7 @@ package org.jeecg.modules.system.service;
import java.util.List;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.entity.SysUserDepart;
import org.jeecg.modules.system.model.DepartIdModel;
@ -37,5 +38,16 @@ public interface ISysUserDepartService extends IService<SysUserDepart> {
/**
* code
*/
public List<SysUser> queryUserByDepCode(String depCode,String realname);
List<SysUser> queryUserByDepCode(String depCode,String realname);
/**
*
* @param departId
* @param username
* @param pageSize
* @param pageNo
* @return
*/
IPage<SysUser> queryDepartUserPageList(String departId, String username, String realname, int pageSize, int pageNo);
}

View File

@ -1,22 +1,21 @@
package org.jeecg.modules.system.service;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.modules.system.entity.SysUser;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.system.model.SysUserSysDepartModel;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* <p>
*
@ -233,4 +232,24 @@ public interface ISysUserService extends IService<SysUser> {
* @return
*/
List<SysUser> queryByDepIds(List<String> departIds, String username);
/**
*
* @param user
* @param selectedRoles id
* @param selectedDeparts id
*/
void saveUser(SysUser user, String selectedRoles, String selectedDeparts);
/**
*
* @param user
* @param roles id
* @param departs id
*/
void editUser(SysUser user, String roles, String departs);
/** userId转为username */
List<String> userIdToUsername(Collection<String> userIdList);
}

View File

@ -0,0 +1,79 @@
package org.jeecg.modules.system.service;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.modules.system.vo.thirdapp.SyncInfoVo;
import java.util.List;
/**
* App
*/
public interface IThirdAppService {
String getAccessToken();
/**
* App<br>
* --> APP
* <br>
* 1. <br>
* 2. AppApp
*
* @return true
*/
boolean syncLocalDepartmentToThirdApp(String ids);
/**
* App<br>
* APP -->
* <br>
* 1. <br>
* 2. AppApp
*
* @return true
*/
SyncInfoVo syncThirdAppDepartmentToLocal(String ids);
/**
* App<br>
* --> APP <br>
* <br>
*
* (1线
*
* 2)
*
* @return
*/
SyncInfoVo syncLocalUserToThirdApp(String ids);
/**
* App<br>
* APP --> <br>
* <br>
*
*
* @return
*/
SyncInfoVo syncThirdAppUserToLocal();
/**
* IDAPP
*
* @param userIdList ID
* @return 0
*/
int removeThirdAppUser(List<String> userIdList);
/**
*
*
* @param message
* @param verifyConfig APP
* @return
*/
boolean sendMessage(MessageDTO message, boolean verifyConfig);
boolean sendMessage(MessageDTO message);
}

View File

@ -1,7 +1,4 @@
package org.jeecg.modules.system.service.impl;
import java.util.HashMap;
import java.util.ArrayList;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -95,6 +92,11 @@ public class SysBaseApiImpl implements ISysBaseAPI {
@Autowired
private ISysPermissionDataRuleService sysPermissionDataRuleService;
@Autowired
private ThirdAppWechatEnterpriseServiceImpl wechatEnterpriseService;
@Autowired
private ThirdAppDingtalkServiceImpl dingtalkService;
@Override
@Cacheable(cacheNames=CacheConstant.SYS_USERS_CACHE, key="#username")
public LoginUser getUserByName(String username) {
@ -201,6 +203,8 @@ public class SysBaseApiImpl implements ISysBaseAPI {
info.setSysUserCode(user.getUsername());
info.setSysUserName(user.getRealname());
info.setSysOrgCode(user.getOrgCode());
}else{
return null;
}
//多部门支持in查询
List<SysDepart> list = departMapper.queryUserDeparts(user.getId());
@ -267,7 +271,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
}
@Override
@Cacheable(value = CacheConstant.SYS_DICT_CACHE,key = "#code")
@Cacheable(value = CacheConstant.SYS_DICT_CACHE,key = "#code", unless = "#result == null ")
public List<DictModel> queryDictItemsByCode(String code) {
return sysDictService.queryDictItemsByCode(code);
}
@ -294,6 +298,13 @@ public class SysBaseApiImpl implements ISysBaseAPI {
message.getTitle(),
message.getContent(),
message.getCategory());
try {
// 同步发送第三方APP消息
wechatEnterpriseService.sendMessage(message, true);
dingtalkService.sendMessage(message, true);
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
}
@Override
@ -305,6 +316,13 @@ public class SysBaseApiImpl implements ISysBaseAPI {
message.getCategory(),
message.getBusType(),
message.getBusId());
try {
// 同步发送第三方APP消息
wechatEnterpriseService.sendMessage(message, true);
dingtalkService.sendMessage(message, true);
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
}
@Override
@ -368,6 +386,13 @@ public class SysBaseApiImpl implements ISysBaseAPI {
webSocket.sendMessage(sysUser.getId(), obj.toJSONString());
}
}
try {
// 同步企业微信、钉钉的消息通知
dingtalkService.sendActionCardMessage(announcement, true);
wechatEnterpriseService.sendTextCardMessage(announcement, true);
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
}
@ -435,6 +460,14 @@ public class SysBaseApiImpl implements ISysBaseAPI {
webSocket.sendMessage(sysUser.getId(), obj.toJSONString());
}
}
try {
// 同步企业微信、钉钉的消息通知
dingtalkService.sendActionCardMessage(announcement, true);
wechatEnterpriseService.sendTextCardMessage(announcement, true);
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
}
@Override
@ -492,8 +525,11 @@ public class SysBaseApiImpl implements ISysBaseAPI {
DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
}else if(dbType.indexOf("postgresql")>=0) {
DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
}else if(dbType.indexOf("mariadb")>=0) {
DB_TYPE = DataBaseConstant.DB_TYPE_MARIADB;
}else {
throw new JeecgBootException("数据库类型:["+dbType+"]不识别!");
log.error("数据库类型:[" + dbType + "]不识别!");
//throw new JeecgBootException("数据库类型:["+dbType+"]不识别!");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
@ -848,7 +884,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
/**
* 36()
* @param orgCodes
* @param usernames
* @return
*/
@Override
@ -867,7 +903,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
/**
* 37()
* @param usernames
* @param orgCodes
* @return
*/
@Override

View File

@ -1,27 +1,27 @@
package org.jeecg.modules.system.service.impl;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.constant.FillRuleConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.common.util.YouBianCodeUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysCategory;
import org.jeecg.modules.system.mapper.SysCategoryMapper;
import org.jeecg.modules.system.model.TreeSelectModel;
import org.jeecg.modules.system.service.ISysCategoryService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description:
* @Author: jeecg-boot
@ -204,4 +204,32 @@ public class SysCategoryServiceImpl extends ServiceImpl<SysCategoryMapper, SysCa
return sb;
}
@Override
public List<String> loadDictItem(String ids) {
return this.loadDictItem(ids, true);
}
@Override
public List<String> loadDictItem(String ids, boolean delNotExist) {
String[] idArray = ids.split(",");
LambdaQueryWrapper<SysCategory> query = new LambdaQueryWrapper<>();
query.in(SysCategory::getId, Arrays.asList(idArray));
// 查询数据
List<SysCategory> list = super.list(query);
// 取出name并返回
List<String> textList;
// update-begin--author:sunjianlei--date:20210514--for新增delNotExist参数设为false不删除数据库里不存在的key ----
if (delNotExist) {
textList = list.stream().map(SysCategory::getName).collect(Collectors.toList());
} else {
textList = new ArrayList<>();
for (String id : idArray) {
List<SysCategory> res = list.stream().filter(i -> id.equals(i.getId())).collect(Collectors.toList());
textList.add(res.size() > 0 ? res.get(0).getName() : id);
}
}
// update-end--author:sunjianlei--date:20210514--for新增delNotExist参数设为false不删除数据库里不存在的key ----
return textList;
}
}

View File

@ -1,8 +1,11 @@
package org.jeecg.modules.system.service.impl;
import java.util.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
@ -21,10 +24,7 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.util.internal.StringUtil;
import java.util.*;
/**
* <p>
@ -468,7 +468,8 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
SysDepart depart = list.get(i);
SysDepartTreeModel treeModel = new SysDepartTreeModel(depart);
//TODO 异步树加载key拼接__+时间戳,以便于每次展开节点会刷新数据
treeModel.setKey(treeModel.getKey()+"__"+System.currentTimeMillis());
//treeModel.setKey(treeModel.getKey()+"__"+System.currentTimeMillis());
treeModel.setKey(treeModel.getKey());
Integer count=this.baseMapper.queryCountByPid(depart.getId());
if(count>0){
treeModel.setIsLeaf(false);
@ -479,6 +480,59 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
}
return records;
}
@Override
public JSONObject queryAllParentIdByDepartId(String departId) {
JSONObject result = new JSONObject();
for (String id : departId.split(",")) {
JSONObject all = this.queryAllParentId("id", id);
result.put(id, all);
}
return result;
}
@Override
public JSONObject queryAllParentIdByOrgCode(String orgCode) {
JSONObject result = new JSONObject();
for (String code : orgCode.split(",")) {
JSONObject all = this.queryAllParentId("org_code", code);
result.put(code, all);
}
return result;
}
/**
* ID
*
* @param fieldName
* @param value
*/
private JSONObject queryAllParentId(String fieldName, String value) {
JSONObject data = new JSONObject();
// 父ID集合有序
data.put("parentIds", new JSONArray());
// 父ID的部门数据key是idvalue是数据
data.put("parentMap", new JSONObject());
this.queryAllParentIdRecursion(fieldName, value, data);
return data;
}
/**
*
*/
private void queryAllParentIdRecursion(String fieldName, String value, JSONObject data) {
QueryWrapper<SysDepart> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(fieldName, value);
SysDepart depart = super.getOne(queryWrapper);
if (depart != null) {
data.getJSONArray("parentIds").add(0, depart.getId());
data.getJSONObject("parentMap").put(depart.getId(), depart);
if (oConvertUtils.isNotEmpty(depart.getParentId())) {
this.queryAllParentIdRecursion("id", depart.getParentId(), data);
}
}
}
@Override
public SysDepart queryCompByOrgCode(String orgCode) {
int length = YouBianCodeUtil.zhanweiLength;

View File

@ -9,6 +9,7 @@ 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.DictQuery;
import org.jeecg.common.util.SqlInjectionUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysDict;
import org.jeecg.modules.system.entity.SysDictItem;
@ -50,7 +51,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
* @return
*/
@Override
@Cacheable(value = CacheConstant.SYS_DICT_CACHE,key = "#code")
@Cacheable(value = CacheConstant.SYS_DICT_CACHE,key = "#code", unless = "#result == null ")
public List<DictModel> queryDictItemsByCode(String code) {
log.debug("无缓存dictCache的时候调用这里");
return sysDictMapper.queryDictItemsByCode(code);
@ -86,7 +87,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
*/
@Override
@Cacheable(value = CacheConstant.SYS_DICT_CACHE,key = "#code+':'+#key")
@Cacheable(value = CacheConstant.SYS_DICT_CACHE,key = "#code+':'+#key", unless = "#result == null ")
public String queryDictTextByKey(String code, String key) {
log.debug("无缓存dictText的时候调用这里");
return sysDictMapper.queryDictTextByKey(code, key);
@ -123,12 +124,17 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
* @return
*/
@Override
@Cacheable(value = CacheConstant.SYS_DICT_TABLE_CACHE)
@Cacheable(value = CacheConstant.SYS_DICT_TABLE_CACHE, unless = "#result == null ")
public String queryTableDictTextByKey(String table,String text,String code, String key) {
log.debug("无缓存dictTable的时候调用这里");
return sysDictMapper.queryTableDictTextByKey(table,text,code,key);
}
@Override
public List<String> queryTableDictByKeys(String table, String text, String code, String keys) {
return this.queryTableDictByKeys(table, text, code, keys, true);
}
/**
* table text code textvalue
* dictTableCacheredis10
@ -136,28 +142,33 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
* @param text
* @param code
* @param keys ()
* @param delNotExist truefalsekeykey
* @return
*/
@Override
//update-begin--Author:lvdandan Date:20201204 forJT-36【online】树形列表bug修改后还是显示原来值 暂时去掉缓存
//@Cacheable(value = CacheConstant.SYS_DICT_TABLE_BY_KEYS_CACHE)
//update-end--Author:lvdandan Date:20201204 forJT-36【online】树形列表bug修改后还是显示原来值 暂时去掉缓存
public List<String> queryTableDictByKeys(String table, String text, String code, String keys) {
public List<String> queryTableDictByKeys(String table, String text, String code, String keys, boolean delNotExist) {
if(oConvertUtils.isEmpty(keys)){
return null;
}
String[] keyArray = keys.split(",");
List<DictModel> dicts = sysDictMapper.queryTableDictByKeys(table, text, code, keyArray);
List<String> texts = new ArrayList<>(dicts.size());
// update-begin--author:sunjianlei--date:20210514--for新增delNotExist参数设为false不删除数据库里不存在的key ----
// 查询出来的顺序可能是乱的,需要排个序
for (String key : keyArray) {
for (DictModel dict : dicts) {
if (key.equals(dict.getValue())) {
texts.add(dict.getText());
break;
}
List<DictModel> res = dicts.stream().filter(i -> key.equals(i.getValue())).collect(Collectors.toList());
if (res.size() > 0) {
texts.add(res.get(0).getText());
} else if (!delNotExist) {
texts.add(key);
}
}
// update-end--author:sunjianlei--date:20210514--for新增delNotExist参数设为false不删除数据库里不存在的key ----
return texts;
}
@ -205,12 +216,49 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
}
@Override
public List<DictModel> queryLittleTableDictItems(String table, String text, String code, String keyword, int pageSize) {
public List<DictModel> queryLittleTableDictItems(String table, String text, String code, String condition, String keyword, int pageSize) {
Page<DictModel> page = new Page<DictModel>(1, pageSize);
IPage<DictModel> pageList = baseMapper.queryTableDictItems(page, table, text, code, "%"+keyword+"%");
page.setSearchCount(false);
String filterSql = getFilterSql(text, code, condition, keyword);
IPage<DictModel> pageList = baseMapper.queryTableDictWithFilter(page, table, text, code, filterSql);
return pageList.getRecords();
}
/**
*
* @param text
* @param code
* @param condition
* @param keyword
* @return
*/
private String getFilterSql(String text, String code, String condition, String keyword){
String keywordSql = null, filterSql = "", sql_where = " where ";
if(oConvertUtils.isNotEmpty(keyword)){
// 判断是否是多选
if (keyword.contains(",")) {
String inKeywords = "\"" + keyword.replaceAll(",", "\",\"") + "\"";
keywordSql = "(" + text + " in (" + inKeywords + ") or " + code + " in (" + inKeywords + "))";
} else {
keywordSql = "("+text + " like '%"+keyword+"%' or "+ code + " like '%"+keyword+"%')";
}
}
if(oConvertUtils.isNotEmpty(condition) && oConvertUtils.isNotEmpty(keywordSql)){
filterSql+= sql_where + condition + " and " + keywordSql;
}else if(oConvertUtils.isNotEmpty(condition)){
filterSql+= sql_where + condition;
}else if(oConvertUtils.isNotEmpty(keywordSql)){
filterSql+= sql_where + keywordSql;
}
return filterSql;
}
@Override
public List<DictModel> queryAllTableDictItems(String table, String text, String code, String condition, String keyword) {
String filterSql = getFilterSql(text, code, condition, keyword);
List<DictModel> ls = baseMapper.queryAllTableDictItems(table, text, code, filterSql);
return ls;
}
@Override
public List<TreeSelectModel> queryTreeList(Map<String, String> query,String table, String text, String code, String pidField,String pid,String hasChildField) {
return baseMapper.queryTreeList(query,table, text, code, pidField, pid,hasChildField);
@ -238,4 +286,61 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
Page<DictModel> pageList = baseMapper.queryDictTablePageList(page, query);
return pageList.getRecords();
}
@Override
public List<DictModel> getDictItems(String dictCode) {
List<DictModel> ls;
if (dictCode.contains(",")) {
//关联表字典举例sys_user,realname,id
String[] params = dictCode.split(",");
if (params.length < 3) {
// 字典Code格式不正确
return null;
}
//SQL注入校验只限制非法串改数据库
final String[] sqlInjCheck = {params[0], params[1], params[2]};
SqlInjectionUtil.filterContent(sqlInjCheck);
if (params.length == 4) {
// SQL注入校验查询条件SQL 特殊check此方法仅供此处使用
SqlInjectionUtil.specialFilterContent(params[3]);
ls = this.queryTableDictItemsByCodeAndFilter(params[0], params[1], params[2], params[3]);
} else if (params.length == 3) {
ls = this.queryTableDictItemsByCode(params[0], params[1], params[2]);
} else {
// 字典Code格式不正确
return null;
}
} else {
//字典表
ls = this.queryDictItemsByCode(dictCode);
}
return ls;
}
@Override
public List<DictModel> loadDict(String dictCode, String keyword, Integer pageSize) {
if (dictCode.contains(",")) {
//update-begin-author:taoyan date:20210329 for: 下拉搜索不支持表名后加查询条件
String[] params = dictCode.split(",");
String condition = null;
if (params.length != 3 && params.length != 4) {
// 字典Code格式不正确
return null;
} else if (params.length == 4) {
condition = params[3];
}
List<DictModel> ls;
if (pageSize != null) {
ls = this.queryLittleTableDictItems(params[0], params[1], params[2], condition, keyword, pageSize);
} else {
ls = this.queryAllTableDictItems(params[0], params[1], params[2], condition, keyword);
}
//update-end-author:taoyan date:20210329 for: 下拉搜索不支持表名后加查询条件
return ls;
} else {
// 字典Code格式不正确
return null;
}
}
}

View File

@ -1,5 +1,6 @@
package org.jeecg.modules.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.system.entity.SysPosition;
import org.jeecg.modules.system.mapper.SysPositionMapper;
@ -15,4 +16,11 @@ import org.springframework.stereotype.Service;
@Service
public class SysPositionServiceImpl extends ServiceImpl<SysPositionMapper, SysPosition> implements ISysPositionService {
@Override
public SysPosition getByCode(String code) {
LambdaQueryWrapper<SysPosition> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysPosition::getCode, code);
return super.getOne(queryWrapper);
}
}

View File

@ -1,7 +1,9 @@
package org.jeecg.modules.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.common.util.oConvertUtils;
@ -14,12 +16,10 @@ 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.service.ISysThirdAccountService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.Date;
import java.util.List;
/**
@ -55,7 +55,8 @@ public class SysThirdAccountServiceImpl extends ServiceImpl<SysThirdAccountMappe
thirdQuery.eq(SysThirdAccount::getThirdType,account.getThirdType());
SysThirdAccount sysThirdAccounts = sysThirdAccountMapper.selectOne(thirdQuery);
if(sysThirdAccounts!=null){
sysThirdAccountMapper.deleteById(sysThirdAccounts.getId());
sysThirdAccount.setThirdUserId(sysThirdAccounts.getThirdUserId());
sysThirdAccountMapper.deleteById(sysThirdAccounts.getId());
}
//更新用户账户表sys_user_id
sysThirdAccountMapper.update(sysThirdAccount,query);
@ -67,6 +68,13 @@ public class SysThirdAccountServiceImpl extends ServiceImpl<SysThirdAccountMappe
LambdaQueryWrapper<SysThirdAccount> query = new LambdaQueryWrapper<>();
query.eq(SysThirdAccount::getThirdUserUuid,thirdUserUuid);
SysThirdAccount account = sysThirdAccountMapper.selectOne(query);
//通过用户名查询数据库是否已存在
SysUser userByName = sysUserMapper.getUserByName(thirdUserUuid);
if(null!=userByName){
//如果账号存在的话,则自动加上一个时间戳
String format = DateUtils.yyyymmddhhmmss.get().format(new Date());
thirdUserUuid = thirdUserUuid + format;
}
//添加用户
SysUser user = new SysUser();
user.setActivitiSync(CommonConstant.ACT_SYNC_0);
@ -103,4 +111,26 @@ public class SysThirdAccountServiceImpl extends ServiceImpl<SysThirdAccountMappe
sysUserRoleMapper.insert(userRole);
return userid;
}
@Override
public SysThirdAccount getOneBySysUserId(String sysUserId, String thirdType) {
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysThirdAccount::getSysUserId, sysUserId);
queryWrapper.eq(SysThirdAccount::getThirdType, thirdType);
return super.getOne(queryWrapper);
}
@Override
public SysThirdAccount getOneByThirdUserId(String thirdUserId, String thirdType) {
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysThirdAccount::getThirdUserId, thirdUserId);
queryWrapper.eq(SysThirdAccount::getThirdType, thirdType);
return super.getOne(queryWrapper);
}
@Override
public List<SysThirdAccount> listThirdUserIdByUsername(String[] sysUsernameArr, String thirdType) {
return sysThirdAccountMapper.selectThirdIdsByUsername(sysUsernameArr, thirdType);
}
}

View File

@ -1,11 +1,15 @@
package org.jeecg.modules.system.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUser;
@ -100,34 +104,58 @@ public class SysUserDepartServiceImpl extends ServiceImpl<SysUserDepartMapper, S
*/
@Override
public List<SysUser> queryUserByDepCode(String depCode,String realname) {
LambdaQueryWrapper<SysDepart> queryByDepCode = new LambdaQueryWrapper<SysDepart>();
queryByDepCode.likeRight(SysDepart::getOrgCode,depCode);
List<SysDepart> sysDepartList = sysDepartService.list(queryByDepCode);
List<String> depIds = sysDepartList.stream().map(SysDepart::getId).collect(Collectors.toList());
LambdaQueryWrapper<SysUserDepart> queryUDep = new LambdaQueryWrapper<SysUserDepart>();
queryUDep.in(SysUserDepart::getDepId, depIds);
List<String> userIdList = new ArrayList<>();
List<SysUserDepart> uDepList = this.list(queryUDep);
if(uDepList != null && uDepList.size() > 0) {
for(SysUserDepart uDep : uDepList) {
userIdList.add(uDep.getUserId());
}
LambdaQueryWrapper<SysUser> queryUser = new LambdaQueryWrapper<SysUser>();
queryUser.in(SysUser::getId,userIdList);
if(oConvertUtils.isNotEmpty(realname)){
queryUser.like(SysUser::getRealname,realname.trim());
}
List<SysUser> userList = (List<SysUser>) sysUserService.list(queryUser);
//update-begin-author:taoyan date:201905047 for:接口调用查询返回结果不能返回密码相关信息
for (SysUser sysUser : userList) {
sysUser.setSalt("");
sysUser.setPassword("");
}
//update-end-author:taoyan date:201905047 for:接口调用查询返回结果不能返回密码相关信息
return userList;
//update-begin-author:taoyan date:20210422 for: 根据部门选择用户接口代码优化
if(oConvertUtils.isNotEmpty(realname)){
realname = realname.trim();
}
return new ArrayList<SysUser>();
List<SysUser> userList = this.baseMapper.queryDepartUserList(depCode, realname);
Map<String, SysUser> map = new HashMap<String, SysUser>();
for (SysUser sysUser : userList) {
// 返回的用户数据去掉密码信息
sysUser.setSalt("");
sysUser.setPassword("");
map.put(sysUser.getId(), sysUser);
}
return new ArrayList<SysUser>(map.values());
//update-end-author:taoyan date:20210422 for: 根据部门选择用户接口代码优化
}
@Override
public IPage<SysUser> queryDepartUserPageList(String departId, String username, String realname, int pageSize, int pageNo) {
IPage<SysUser> pageList = null;
// 部门ID不存在 直接查询用户表即可
Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
if(oConvertUtils.isEmpty(departId)){
LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
if(oConvertUtils.isNotEmpty(username)){
query.like(SysUser::getUsername, username);
}
pageList = sysUserService.page(page, query);
}else{
// 有部门ID 需要走自定义sql
SysDepart sysDepart = sysDepartService.getById(departId);
pageList = this.baseMapper.queryDepartUserPageList(page, sysDepart.getOrgCode(), username, realname);
}
List<SysUser> userList = pageList.getRecords();
if(userList!=null && userList.size()>0){
List<String> userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList());
Map<String, SysUser> map = new HashMap<String, SysUser>();
if(userIds!=null && userIds.size()>0){
// 查部门名称
Map<String,String> useDepNames = sysUserService.getDepNamesByUserIds(userIds);
userList.forEach(item->{
//TODO 临时借用这个字段用于页面展示
item.setOrgCodeTxt(useDepNames.get(item.getId()));
item.setSalt("");
item.setPassword("");
// 去重
map.put(item.getId(), item);
});
}
pageList.setRecords(new ArrayList<SysUser>(map.values()));
}
return pageList;
}
}

View File

@ -10,12 +10,12 @@ 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.vo.LoginUser;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.mapper.*;
import org.jeecg.modules.system.model.SysUserSysDepartModel;
@ -62,6 +62,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
private SysDepartRoleMapper sysDepartRoleMapper;
@Resource
private BaseCommonService baseCommonService;
@Autowired
private SysThirdAccountMapper sysThirdAccountMapper;
@Autowired
ThirdAppWechatEnterpriseServiceImpl wechatEnterpriseService;
@Autowired
ThirdAppDingtalkServiceImpl dingtalkService;
@Override
@CacheEvict(value = {CacheConstant.SYS_USERS_CACHE}, allEntries = true)
@ -408,6 +414,16 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
line += sysUserDepartMapper.delete(new LambdaQueryWrapper<SysUserDepart>().in(SysUserDepart::getUserId, userIds));
//3. 删除用户角色关系
line += sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, userIds));
//4.同步删除第三方App的用户
try {
dingtalkService.removeThirdAppUser(userIds);
wechatEnterpriseService.removeThirdAppUser(userIds);
} catch (Exception e) {
log.error("同步删除第三方App的用户失败", e);
}
//5. 删除第三方用户表因为第4步需要用到第三方用户表所以在他之后删
line += sysThirdAccountMapper.delete(new LambdaQueryWrapper<SysThirdAccount>().in(SysThirdAccount::getSysUserId, userIds));
return line != 0;
}
@ -439,4 +455,88 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
return userMapper.queryByDepIds(departIds,username);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveUser(SysUser user, String selectedRoles, String selectedDeparts) {
//step.1 保存用户
this.save(user);
//step.2 保存角色
if(oConvertUtils.isNotEmpty(selectedRoles)) {
String[] arr = selectedRoles.split(",");
for (String roleId : arr) {
SysUserRole userRole = new SysUserRole(user.getId(), roleId);
sysUserRoleMapper.insert(userRole);
}
}
//step.3 保存所属部门
if(oConvertUtils.isNotEmpty(selectedDeparts)) {
String[] arr = selectedDeparts.split(",");
for (String deaprtId : arr) {
SysUserDepart userDeaprt = new SysUserDepart(user.getId(), deaprtId);
sysUserDepartMapper.insert(userDeaprt);
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
public void editUser(SysUser user, String roles, String departs) {
//step.1 修改用户基础信息
this.updateById(user);
//step.2 修改角色
//处理用户角色 先删后加
sysUserRoleMapper.delete(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, user.getId()));
if(oConvertUtils.isNotEmpty(roles)) {
String[] arr = roles.split(",");
for (String roleId : arr) {
SysUserRole userRole = new SysUserRole(user.getId(), roleId);
sysUserRoleMapper.insert(userRole);
}
}
//step.3 修改部门
String[] arr = {};
if(oConvertUtils.isNotEmpty(departs)){
arr = departs.split(",");
}
//查询已关联部门
List<SysUserDepart> userDepartList = sysUserDepartMapper.selectList(new QueryWrapper<SysUserDepart>().lambda().eq(SysUserDepart::getUserId, user.getId()));
if(userDepartList != null && userDepartList.size()>0){
for(SysUserDepart depart : userDepartList ){
//修改已关联部门删除部门用户角色关系
if(!Arrays.asList(arr).contains(depart.getDepId())){
List<SysDepartRole> sysDepartRoleList = sysDepartRoleMapper.selectList(
new QueryWrapper<SysDepartRole>().lambda().eq(SysDepartRole::getDepartId,depart.getDepId()));
List<String> roleIds = sysDepartRoleList.stream().map(SysDepartRole::getId).collect(Collectors.toList());
if(roleIds != null && roleIds.size()>0){
departRoleUserMapper.delete(new QueryWrapper<SysDepartRoleUser>().lambda().eq(SysDepartRoleUser::getUserId, user.getId())
.in(SysDepartRoleUser::getDroleId,roleIds));
}
}
}
}
//先删后加
sysUserDepartMapper.delete(new QueryWrapper<SysUserDepart>().lambda().eq(SysUserDepart::getUserId, user.getId()));
if(oConvertUtils.isNotEmpty(departs)) {
for (String departId : arr) {
SysUserDepart userDepart = new SysUserDepart(user.getId(), departId);
sysUserDepartMapper.insert(userDepart);
}
}
//step.4 修改手机号和邮箱
// 更新手机号、邮箱空字符串为 null
userMapper.updateNullByEmptyString("email");
userMapper.updateNullByEmptyString("phone");
}
@Override
public List<String> userIdToUsername(Collection<String> userIdList) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SysUser::getId, userIdList);
List<SysUser> userList = super.list(queryWrapper);
return userList.stream().map(SysUser::getUsername).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,769 @@
package org.jeecg.modules.system.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeecg.dingtalk.api.base.JdtBaseAPI;
import com.jeecg.dingtalk.api.core.response.Response;
import com.jeecg.dingtalk.api.core.vo.AccessToken;
import com.jeecg.dingtalk.api.core.vo.PageResult;
import com.jeecg.dingtalk.api.department.JdtDepartmentAPI;
import com.jeecg.dingtalk.api.department.vo.Department;
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.user.JdtUserAPI;
import com.jeecg.dingtalk.api.user.body.GetUserListBody;
import com.jeecg.dingtalk.api.user.vo.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.PasswordUtil;
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.modules.system.entity.*;
import org.jeecg.modules.system.mapper.SysAnnouncementSendMapper;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.vo.thirdapp.JdtDepartmentTreeVo;
import org.jeecg.modules.system.vo.thirdapp.SyncInfoVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* App
*/
@Slf4j
@Service
public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
@Autowired
ThirdAppConfig thirdAppConfig;
@Autowired
private ISysDepartService sysDepartService;
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysThirdAccountService sysThirdAccountService;
@Autowired
private ISysUserDepartService sysUserDepartService;
@Autowired
private ISysPositionService sysPositionService;
@Autowired
private SysAnnouncementSendMapper sysAnnouncementSendMapper;
@Override
public String getAccessToken() {
String appKey = thirdAppConfig.getDingtalk().getClientId();
String appSecret = thirdAppConfig.getDingtalk().getClientSecret();
AccessToken accessToken = JdtBaseAPI.getAccessToken(appKey, appSecret);
if (accessToken != null) {
return accessToken.getAccessToken();
}
log.warn("获取AccessToken失败");
return null;
}
@Override
public boolean syncLocalDepartmentToThirdApp(String ids) {
String accessToken = this.getAccessToken();
if (accessToken == null) {
return false;
}
// 获取【钉钉】所有的部门
List<Department> departments = JdtDepartmentAPI.listAll(accessToken);
// 删除钉钉有但本地没有的部门(以本地部门数据为主)(钉钉不能创建同名部门,只能先删除)
List<SysDepart> sysDepartList = sysDepartService.list();
for1:
for (Department department : departments) {
for (SysDepart depart : sysDepartList) {
// id相同代表已存在不删除
String sourceIdentifier = department.getSource_identifier();
if (sourceIdentifier != null && sourceIdentifier.equals(depart.getId())) {
continue for1;
}
}
// 循环到此说明本地没有,删除
int deptId = department.getDept_id();
// 钉钉不允许删除带有用户的部门,所以需要判断下,将有用户的部门的用户移动至根部门
Response<List<String>> userIdRes = JdtUserAPI.getUserListIdByDeptId(deptId, accessToken);
if (userIdRes.isSuccess() && userIdRes.getResult().size() > 0) {
for (String userId : userIdRes.getResult()) {
User updateUser = new User();
updateUser.setUserid(userId);
updateUser.setDept_id_list(1);
JdtUserAPI.update(updateUser, accessToken);
}
}
JdtDepartmentAPI.delete(deptId, accessToken);
}
// 获取本地所有部门树结构
List<SysDepartTreeModel> sysDepartsTree = sysDepartService.queryTreeList();
// -- 钉钉不能创建新的顶级部门所以新的顶级部门的parentId就为1
Department parent = new Department();
parent.setDept_id(1);
// 递归同步部门
departments = JdtDepartmentAPI.listAll(accessToken);
this.syncDepartmentRecursion(sysDepartsTree, departments, parent, accessToken);
return true;
}
// 递归同步部门到本地
public void syncDepartmentRecursion(List<SysDepartTreeModel> sysDepartsTree, List<Department> departments, Department parent, String accessToken) {
if (sysDepartsTree != null && sysDepartsTree.size() != 0) {
for1:
for (SysDepartTreeModel depart : sysDepartsTree) {
for (Department department : departments) {
// id相同代表已存在执行修改操作
String sourceIdentifier = department.getSource_identifier();
if (sourceIdentifier != null && sourceIdentifier.equals(depart.getId())) {
this.sysDepartToDtDepartment(depart, department, parent.getDept_id());
JdtDepartmentAPI.update(department, accessToken);
// 紧接着同步子级
this.syncDepartmentRecursion(depart.getChildren(), departments, department, accessToken);
// 跳出外部循环
continue for1;
}
}
// 循环到此说明是新部门,直接调接口创建
Department newDepartment = this.sysDepartToDtDepartment(depart, parent.getDept_id());
Response<Integer> response = JdtDepartmentAPI.create(newDepartment, accessToken);
// 创建成功将返回的id绑定到本地
if (response.getResult() != null) {
Department newParent = new Department();
newParent.setDept_id(response.getResult());
// 紧接着同步子级
this.syncDepartmentRecursion(depart.getChildren(), departments, newParent, accessToken);
}
// 收集错误信息
// this.syncUserCollectErrInfo(errCode, sysUser, errInfo);
}
}
}
@Override
public SyncInfoVo syncThirdAppDepartmentToLocal(String ids) {
SyncInfoVo syncInfo = new SyncInfoVo();
String accessToken = this.getAccessToken();
if (accessToken == null) {
syncInfo.addFailInfo("accessToken获取失败");
return syncInfo;
}
// 获取【钉钉】所有的部门
List<Department> departments = JdtDepartmentAPI.listAll(accessToken);
String username = JwtUtil.getUserNameByToken(SpringContextUtils.getHttpServletRequest());
List<JdtDepartmentTreeVo> departmentTreeList = JdtDepartmentTreeVo.listToTree(departments);
// 递归同步部门
this.syncDepartmentToLocalRecursion(departmentTreeList, null, username, syncInfo, accessToken);
return syncInfo;
}
public void syncDepartmentToLocalRecursion(List<JdtDepartmentTreeVo> departmentTreeList, String sysParentId, String username, SyncInfoVo syncInfo, String accessToken) {
if (departmentTreeList != null && departmentTreeList.size() != 0) {
for (JdtDepartmentTreeVo departmentTree : departmentTreeList) {
LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
// 根据 source_identifier 字段查询
queryWrapper.eq(SysDepart::getId, departmentTree.getSource_identifier());
SysDepart sysDepart = sysDepartService.getOne(queryWrapper);
if (sysDepart != null) {
// 执行更新操作
SysDepart updateSysDepart = this.dtDepartmentToSysDepart(departmentTree, sysDepart);
if (sysParentId != null) {
updateSysDepart.setParentId(sysParentId);
}
try {
sysDepartService.updateDepartDataById(updateSysDepart, username);
String str = String.format("部门 %s 更新成功!", updateSysDepart.getDepartName());
syncInfo.addSuccessInfo(str);
} catch (Exception e) {
this.syncDepartCollectErrInfo(e, departmentTree, syncInfo);
}
if (departmentTree.hasChildren()) {
// 紧接着同步子级
this.syncDepartmentToLocalRecursion(departmentTree.getChildren(), updateSysDepart.getId(), username, syncInfo, accessToken);
}
} else {
// 执行新增操作
SysDepart newSysDepart = this.dtDepartmentToSysDepart(departmentTree, null);
if (sysParentId != null) {
newSysDepart.setParentId(sysParentId);
}
try {
sysDepartService.saveDepartData(newSysDepart, username);
// 更新钉钉 source_identifier
Department updateDtDepart = new Department();
updateDtDepart.setDept_id(departmentTree.getDept_id());
updateDtDepart.setSource_identifier(newSysDepart.getId());
Response response = JdtDepartmentAPI.update(updateDtDepart, accessToken);
if (!response.isSuccess()) {
throw new RuntimeException(response.getErrmsg());
}
String str = String.format("部门 %s 创建成功!", newSysDepart.getDepartName());
syncInfo.addSuccessInfo(str);
} catch (Exception e) {
this.syncDepartCollectErrInfo(e, departmentTree, syncInfo);
}
// 紧接着同步子级
if (departmentTree.hasChildren()) {
this.syncDepartmentToLocalRecursion(departmentTree.getChildren(), newSysDepart.getId(), username, syncInfo, accessToken);
}
}
}
}
}
private boolean syncDepartCollectErrInfo(Exception e, Department department, SyncInfoVo syncInfo) {
String msg;
if (e instanceof DuplicateKeyException) {
msg = e.getCause().getMessage();
} else {
msg = e.getMessage();
}
String str = String.format("部门 %s(%s) 同步失败!错误信息:%s", department.getName(), department.getDept_id(), msg);
syncInfo.addFailInfo(str);
return false;
}
@Override
public SyncInfoVo syncLocalUserToThirdApp(String ids) {
SyncInfoVo syncInfo = new SyncInfoVo();
String accessToken = this.getAccessToken();
if (accessToken == null) {
syncInfo.addFailInfo("accessToken获取失败");
return syncInfo;
}
List<SysUser> sysUsers;
if (StringUtils.isNotBlank(ids)) {
String[] idList = ids.split(",");
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SysUser::getId, (Object[]) idList);
// 获取本地指定用户
sysUsers = sysUserService.list(queryWrapper);
} else {
// 获取本地所有用户
sysUsers = sysUserService.list();
}
// 查询钉钉所有的部门,用于同步用户和部门的关系
List<Department> allDepartment = JdtDepartmentAPI.listAll(accessToken);
for (SysUser sysUser : sysUsers) {
// 外部模拟登陆临时账号,不同步
if ("_reserve_user_external".equals(sysUser.getUsername())) {
continue;
}
// 钉钉用户信息不为null代表已同步过
Response<User> dtUserInfo;
/*
*
* 1. sys_third_account
* 2. username
*/
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneBySysUserId(sysUser.getId(), ThirdAppConfig.DINGTALK.toLowerCase());
if (sysThirdAccount != null && oConvertUtils.isNotEmpty(sysThirdAccount.getThirdUserId())) {
// sys_third_account 表匹配成功通过第三方userId查询出第三方userInfo
dtUserInfo = JdtUserAPI.getUserById(sysThirdAccount.getThirdUserId(), accessToken);
} else {
// 手机号匹配
Response<String> thirdUserId = JdtUserAPI.getUseridByMobile(sysUser.getPhone(), accessToken);
// 手机号匹配成功
if (thirdUserId.isSuccess() && oConvertUtils.isNotEmpty(thirdUserId.getResult())) {
// 通过查询到的userId查询用户详情
dtUserInfo = JdtUserAPI.getUserById(thirdUserId.getResult(), accessToken);
} else {
// 手机号匹配失败尝试使用username匹配
dtUserInfo = JdtUserAPI.getUserById(sysUser.getUsername(), accessToken);
}
}
String dtUserId;
// api 接口是否执行成功
boolean apiSuccess;
// 已同步就更新,否则就创建
if (dtUserInfo != null && dtUserInfo.isSuccess() && dtUserInfo.getResult() != null) {
User dtUser = dtUserInfo.getResult();
dtUserId = dtUser.getUserid();
User updateQwUser = this.sysUserToDtUser(sysUser, dtUser, allDepartment);
Response<JSONObject> updateRes = JdtUserAPI.update(updateQwUser, accessToken);
// 收集成功/失败信息
apiSuccess = this.syncUserCollectErrInfo(updateRes, sysUser, syncInfo);
} else {
User newQwUser = this.sysUserToDtUser(sysUser, allDepartment);
Response<String> createRes = JdtUserAPI.create(newQwUser, accessToken);
dtUserId = createRes.getResult();
// 收集成功/失败信息
apiSuccess = this.syncUserCollectErrInfo(createRes, sysUser, syncInfo);
}
// api 接口执行成功,并且 sys_third_account 表匹配失败,就向 sys_third_account 里插入一条数据
if (apiSuccess && (sysThirdAccount == null || oConvertUtils.isEmpty(sysThirdAccount.getThirdUserId()))) {
if (sysThirdAccount == null) {
sysThirdAccount = new SysThirdAccount();
sysThirdAccount.setSysUserId(sysUser.getId());
sysThirdAccount.setStatus(1);
sysThirdAccount.setDelFlag(0);
sysThirdAccount.setThirdType(ThirdAppConfig.DINGTALK.toLowerCase());
}
// 设置第三方app用户ID
sysThirdAccount.setThirdUserId(dtUserId);
sysThirdAccountService.saveOrUpdate(sysThirdAccount);
}
}
return syncInfo;
}
@Override
public SyncInfoVo syncThirdAppUserToLocal() {
SyncInfoVo syncInfo = new SyncInfoVo();
String accessToken = this.getAccessToken();
if (accessToken == null) {
syncInfo.addFailInfo("accessToken获取失败");
return syncInfo;
}
// 获取本地用户
List<SysUser> sysUsersList = sysUserService.list();
// 查询钉钉所有的部门,用于同步用户和部门的关系
List<Department> allDepartment = JdtDepartmentAPI.listAll(accessToken);
// 根据钉钉部门查询所有钉钉用户,用于反向同步到本地
List<User> ddUserList = this.getDtAllUserByDepartment(allDepartment, accessToken);
for (User dtUserInfo : ddUserList) {
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneByThirdUserId(dtUserInfo.getUserid(), ThirdAppConfig.DINGTALK.toLowerCase());
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) {
SysUser sysUserTemp = collect.get(0);
// 循环到此说明用户匹配成功,进行更新操作
SysUser updateSysUser = this.dtUserToSysUser(dtUserInfo, sysUserTemp);
try {
sysUserService.updateById(updateSysUser);
String str = String.format("用户 %s(%s) 更新成功!", updateSysUser.getRealname(), updateSysUser.getUsername());
syncInfo.addSuccessInfo(str);
} catch (Exception e) {
this.syncUserCollectErrInfo(e, dtUserInfo, syncInfo);
}
//第三方账号关系表
this.thirdAccountSaveOrUpdate(sysThirdAccount, updateSysUser.getId(), dtUserInfo.getUserid());
}else{
// 如果没有匹配到用户,则走创建逻辑
SysUser newSysUser = this.dtUserToSysUser(dtUserInfo);
try {
sysUserService.save(newSysUser);
String str = String.format("用户 %s(%s) 创建成功!", newSysUser.getRealname(), newSysUser.getUsername());
syncInfo.addSuccessInfo(str);
} catch (Exception e) {
this.syncUserCollectErrInfo(e, dtUserInfo, syncInfo);
}
//第三方账号关系表
this.thirdAccountSaveOrUpdate(null, newSysUser.getId(), dtUserInfo.getUserid());
}
}
return syncInfo;
}
private List<User> getDtAllUserByDepartment(List<Department> allDepartment, String accessToken) {
// 根据钉钉部门查询所有钉钉用户,用于反向同步到本地
List<User> userList = new ArrayList<>();
for (Department department : allDepartment) {
this.getUserListByDeptIdRecursion(department.getDept_id(), 0, userList, accessToken);
}
return userList;
}
/**
*
*/
private void getUserListByDeptIdRecursion(int deptId, int cursor, List<User> userList, String accessToken) {
// 根据钉钉部门查询所有钉钉用户,用于反向同步到本地
GetUserListBody getUserListBody = new GetUserListBody(deptId, cursor, 100);
Response<PageResult<User>> response = JdtUserAPI.getUserListByDeptId(getUserListBody, accessToken);
if (response.isSuccess()) {
PageResult<User> page = response.getResult();
userList.addAll(page.getList());
if (page.getHas_more()) {
this.getUserListByDeptIdRecursion(deptId, page.getNext_cursor(), userList, accessToken);
}
}
}
/**
*
*
* @param sysThirdAccount null
* @param sysUserId ID
* @param dtUserId ID
*/
private void thirdAccountSaveOrUpdate(SysThirdAccount sysThirdAccount, String sysUserId, String dtUserId) {
if (sysThirdAccount == null) {
sysThirdAccount = new SysThirdAccount();
sysThirdAccount.setSysUserId(sysUserId);
sysThirdAccount.setStatus(1);
sysThirdAccount.setDelFlag(0);
sysThirdAccount.setThirdType(ThirdAppConfig.DINGTALK.toLowerCase());
}
sysThirdAccount.setThirdUserId(dtUserId);
sysThirdAccountService.saveOrUpdate(sysThirdAccount);
}
/**
*
*/
private boolean syncUserCollectErrInfo(Response<?> response, SysUser sysUser, SyncInfoVo syncInfo) {
if (!response.isSuccess()) {
String str = String.format("用户 %s(%s) 同步失败!错误码:%s——%s", sysUser.getUsername(), sysUser.getRealname(), response.getErrcode(), response.getErrmsg());
syncInfo.addFailInfo(str);
return false;
} else {
String str = String.format("用户 %s(%s) 同步成功!", sysUser.getUsername(), sysUser.getRealname());
syncInfo.addSuccessInfo(str);
return true;
}
}
/**
*
*/
private boolean syncUserCollectErrInfo(Exception e, User dtUser, SyncInfoVo syncInfo) {
String msg;
if (e instanceof DuplicateKeyException) {
msg = e.getCause().getMessage();
} else {
msg = e.getMessage();
}
String str = String.format("用户 %s(%s) 同步失败!错误信息:%s", dtUser.getUserid(), dtUser.getName(), msg);
syncInfo.addFailInfo(str);
return false;
}
/**
* SysUserUser
*/
private User sysUserToDtUser(SysUser sysUser, List<Department> allDepartment) {
User user = new User();
// 通过 username 来关联
user.setUserid(sysUser.getUsername());
return this.sysUserToDtUser(sysUser, user, allDepartment);
}
/**
* SysUserUser
*/
private User sysUserToDtUser(SysUser sysUser, User user, List<Department> allDepartment) {
user.setName(sysUser.getRealname());
user.setMobile(sysUser.getPhone());
user.setTelephone(sysUser.getTelephone());
user.setJob_number(sysUser.getWorkNo());
// 职务翻译
if (oConvertUtils.isNotEmpty(sysUser.getPost())) {
SysPosition position = sysPositionService.getByCode(sysUser.getPost());
if (position != null) {
user.setTitle(position.getName());
}
}
user.setEmail(sysUser.getEmail());
// 查询并同步用户部门关系
List<SysDepart> departList = this.getUserDepart(sysUser);
if (departList != null) {
List<Integer> departmentIdList = new ArrayList<>();
for (SysDepart sysDepart : departList) {
// 企业微信的部门id
Department department = this.getDepartmentByDepartId(sysDepart.getId(), allDepartment);
if (department != null) {
departmentIdList.add(department.getDept_id());
}
}
user.setDept_id_list(departmentIdList.toArray(new Integer[]{}));
user.setDept_order_list(null);
}
if (oConvertUtils.isEmpty(user.getDept_id_list())) {
// 没有找到匹配部门,同步到根部门下
user.setDept_id_list(1);
user.setDept_order_list(null);
}
// --- 钉钉没有逻辑删除功能
// sysUser.getDelFlag()
// --- 钉钉没有冻结、启用禁用功能
// sysUser.getStatus()
return user;
}
/**
* UserSysUser
*/
private SysUser dtUserToSysUser(User dtUser) {
SysUser sysUser = new SysUser();
sysUser.setDelFlag(0);
// 通过 username 来关联
sysUser.setUsername(dtUser.getUserid());
// 密码默认为 “123456”随机加盐
String password = "123456", salt = oConvertUtils.randomGen(8);
String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), password, salt);
sysUser.setSalt(salt);
sysUser.setPassword(passwordEncode);
return this.dtUserToSysUser(dtUser, sysUser);
}
/**
* UserSysUser
*/
private SysUser dtUserToSysUser(User dtUser, SysUser oldSysUser) {
SysUser sysUser = new SysUser();
BeanUtils.copyProperties(oldSysUser, sysUser);
sysUser.setRealname(dtUser.getName());
sysUser.setPhone(dtUser.getMobile());
sysUser.setTelephone(dtUser.getTelephone());
// 因为唯一键约束的原因,如果原数据和旧数据相同,就不更新
if (oConvertUtils.isNotEmpty(dtUser.getEmail()) && !dtUser.getEmail().equals(sysUser.getEmail())) {
sysUser.setEmail(dtUser.getEmail());
} else {
sysUser.setEmail(null);
}
// 因为唯一键约束的原因,如果原数据和旧数据相同,就不更新
if (oConvertUtils.isNotEmpty(dtUser.getMobile()) && !dtUser.getMobile().equals(sysUser.getPhone())) {
sysUser.setPhone(dtUser.getMobile());
} else {
sysUser.setPhone(null);
}
sysUser.setWorkNo(null);
// --- 钉钉没有逻辑删除功能
// sysUser.getDelFlag()
// --- 钉钉没有冻结、启用禁用功能
// sysUser.getStatus()
return sysUser;
}
/**
*
*/
private List<SysDepart> getUserDepart(SysUser sysUser) {
// 根据用户部门关系表查询出用户的部门
LambdaQueryWrapper<SysUserDepart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUserDepart::getUserId, sysUser.getId());
List<SysUserDepart> sysUserDepartList = sysUserDepartService.list(queryWrapper);
if (sysUserDepartList.size() == 0) {
return null;
}
// 根据用户部门
LambdaQueryWrapper<SysDepart> departQueryWrapper = new LambdaQueryWrapper<>();
List<String> departIdList = sysUserDepartList.stream().map(SysUserDepart::getDepId).collect(Collectors.toList());
departQueryWrapper.in(SysDepart::getId, departIdList);
List<SysDepart> departList = sysDepartService.list(departQueryWrapper);
return departList.size() == 0 ? null : departList;
}
/**
* sysDepartId
*/
private Department getDepartmentByDepartId(String departId, List<Department> allDepartment) {
for (Department department : allDepartment) {
if (departId.equals(department.getSource_identifier())) {
return department;
}
}
return null;
}
/**
* SysDepartTreeModelDepartment
*/
private Department sysDepartToDtDepartment(SysDepartTreeModel departTree, Integer parentId) {
Department department = new Department();
department.setSource_identifier(departTree.getId());
return this.sysDepartToDtDepartment(departTree, department, parentId);
}
/**
* SysDepartTreeModelDepartment
*/
private Department sysDepartToDtDepartment(SysDepartTreeModel departTree, Department department, Integer parentId) {
department.setName(departTree.getDepartName());
department.setParent_id(parentId);
department.setOrder(departTree.getDepartOrder());
return department;
}
/**
* DepartmentSysDepartTreeModel
*/
private SysDepart dtDepartmentToSysDepart(Department department, SysDepart departTree) {
SysDepart sysDepart = new SysDepart();
if (departTree != null) {
BeanUtils.copyProperties(departTree, sysDepart);
}
sysDepart.setDepartName(department.getName());
sysDepart.setDepartOrder(department.getOrder());
return sysDepart;
}
@Override
public int removeThirdAppUser(List<String> userIdList) {
// 判断启用状态
if (!thirdAppConfig.isDingtalkEnabled()) {
return -1;
}
int count = 0;
if (userIdList != null && userIdList.size() > 0) {
String accessToken = this.getAccessToken();
if (accessToken == null) {
return count;
}
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysThirdAccount::getThirdType, ThirdAppConfig.DINGTALK.toLowerCase());
queryWrapper.in(SysThirdAccount::getSysUserId, userIdList);
// 根据userId获取第三方用户的id
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.list(queryWrapper);
List<String> thirdUserIdList = thirdAccountList.stream().map(SysThirdAccount::getThirdUserId).collect(Collectors.toList());
for (String thirdUserId : thirdUserIdList) {
if (oConvertUtils.isNotEmpty(thirdUserId)) {
// 没有批量删除的接口
Response<JSONObject> response = JdtUserAPI.delete(thirdUserId, accessToken);
if (response.getErrcode() == 0) {
count++;
}
}
}
}
return count;
}
@Override
public boolean sendMessage(MessageDTO message) {
return this.sendMessage(message, false);
}
/**
*
*
* @param message
* @param verifyConfig
* @return
*/
public boolean sendMessage(MessageDTO message, boolean verifyConfig) {
Response<String> response = this.sendMessageResponse(message, verifyConfig);
if (response != null) {
return response.isSuccess();
}
return false;
}
public Response<String> sendMessageResponse(MessageDTO message, boolean verifyConfig) {
if (verifyConfig && !thirdAppConfig.isDingtalkEnabled()) {
return null;
}
String accessToken = this.getAccessToken();
if (accessToken == null) {
return null;
}
// 封装钉钉消息
String content = message.getContent();
int agentId = thirdAppConfig.getDingtalk().getAgentIdInt();
Message<TextMessage> textMessage = new Message<>(agentId, new TextMessage(content));
if (message.isToAll()) {
textMessage.setTo_all_user(true);
} else {
String[] toUsers = message.getToUser().split(",");
// 通过第三方账号表查询出第三方userId
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(toUsers, ThirdAppConfig.DINGTALK.toLowerCase());
List<String> dtUserIds = thirdAccountList.stream().map(SysThirdAccount::getThirdUserId).collect(Collectors.toList());
textMessage.setUserid_list(dtUserIds);
}
return JdtMessageAPI.sendTextMessage(textMessage, accessToken);
}
public boolean recallMessage(String msg_task_id) {
Response<JSONObject> response = this.recallMessageResponse(msg_task_id);
if (response == null) {
return false;
}
return response.isSuccess();
}
/**
*
*
* @param msg_task_id
* @return
*/
public Response<JSONObject> recallMessageResponse(String msg_task_id) {
String accessToken = this.getAccessToken();
if (accessToken == null) {
return null;
}
int agentId = thirdAppConfig.getDingtalk().getAgentIdInt();
return JdtMessageAPI.recallMessage(agentId, msg_task_id, getAccessToken());
}
/**
* SysAnnouncement
*
* @param announcement
* @param verifyConfig APP
* @return
*/
public Response<String> sendActionCardMessage(SysAnnouncement announcement, boolean verifyConfig) {
if (verifyConfig && !thirdAppConfig.isDingtalkEnabled()) {
return null;
}
String accessToken = this.getAccessToken();
if (accessToken == null) {
return null;
}
int agentId = thirdAppConfig.getDingtalk().getAgentIdInt();
String markdown = "### " + announcement.getTitile() + "\n" + oConvertUtils.getString(announcement.getMsgAbstract(),"空");
ActionCardMessage actionCard = new ActionCardMessage(markdown);
actionCard.setTitle(announcement.getTitile());
actionCard.setSingle_title("详情");
actionCard.setSingle_url(RestUtil.getBaseUrl() + "/sys/annountCement/show/" + announcement.getId());
Message<ActionCardMessage> actionCardMessage = new Message<>(agentId, actionCard);
if (CommonConstant.MSG_TYPE_ALL.equals(announcement.getMsgType())) {
actionCardMessage.setTo_all_user(true);
return JdtMessageAPI.sendActionCardMessage(actionCardMessage, accessToken);
} else {
// 将userId转为username
String[] userIds = null;
String userId = announcement.getUserIds();
if(oConvertUtils.isNotEmpty(userId)){
userIds = userId.substring(0, (userId.length() - 1)).split(",");
}else{
LambdaQueryWrapper<SysAnnouncementSend> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysAnnouncementSend::getAnntId, announcement.getId());
SysAnnouncementSend sysAnnouncementSend = sysAnnouncementSendMapper.selectOne(queryWrapper);
userIds = new String[] {sysAnnouncementSend.getUserId()};
}
if(userIds!=null){
String[] usernameList = sysUserService.userIdToUsername(Arrays.asList(userIds)).toArray(new String[]{});
// 通过第三方账号表查询出第三方userId
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(usernameList, ThirdAppConfig.DINGTALK.toLowerCase());
List<String> dtUserIds = thirdAccountList.stream().map(SysThirdAccount::getThirdUserId).collect(Collectors.toList());
actionCardMessage.setUserid_list(dtUserIds);
return JdtMessageAPI.sendActionCardMessage(actionCardMessage, accessToken);
}
}
return null;
}
}

View File

@ -0,0 +1,791 @@
package org.jeecg.modules.system.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeecg.qywx.api.base.JwAccessTokenAPI;
import com.jeecg.qywx.api.core.common.AccessToken;
import com.jeecg.qywx.api.department.JwDepartmentAPI;
import com.jeecg.qywx.api.department.vo.DepartMsgResponse;
import com.jeecg.qywx.api.department.vo.Department;
import com.jeecg.qywx.api.message.JwMessageAPI;
import com.jeecg.qywx.api.message.vo.Text;
import com.jeecg.qywx.api.message.vo.TextCard;
import com.jeecg.qywx.api.message.vo.TextCardEntity;
import com.jeecg.qywx.api.message.vo.TextEntity;
import com.jeecg.qywx.api.user.JwUserAPI;
import com.jeecg.qywx.api.user.vo.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.PasswordUtil;
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.modules.system.entity.*;
import org.jeecg.modules.system.mapper.SysAnnouncementSendMapper;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.vo.thirdapp.JwDepartmentTreeVo;
import org.jeecg.modules.system.vo.thirdapp.SyncInfoVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* App
*/
@Slf4j
@Service
public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
@Autowired
ThirdAppConfig thirdAppConfig;
@Autowired
private ISysDepartService sysDepartService;
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysThirdAccountService sysThirdAccountService;
@Autowired
private ISysUserDepartService sysUserDepartService;
@Autowired
private ISysPositionService sysPositionService;
@Autowired
private SysAnnouncementSendMapper sysAnnouncementSendMapper;
@Override
public String getAccessToken() {
String CORP_ID = thirdAppConfig.getWechatEnterprise().getClientId();
String SECRET = thirdAppConfig.getWechatEnterprise().getClientSecret();
AccessToken accessToken = JwAccessTokenAPI.getAccessToken(CORP_ID, SECRET);
if (accessToken != null) {
return accessToken.getAccesstoken();
}
log.warn("获取AccessToken失败");
return null;
}
/** 获取APPToken新版企业微信的秘钥是分开的 */
public String getAppAccessToken() {
String CORP_ID = thirdAppConfig.getWechatEnterprise().getClientId();
String SECRET = thirdAppConfig.getWechatEnterprise().getAgentAppSecret();
// 如果没有配置APP秘钥就说明是老企业可以通用秘钥
if (oConvertUtils.isEmpty(SECRET)) {
SECRET = thirdAppConfig.getWechatEnterprise().getClientSecret();
}
AccessToken accessToken = JwAccessTokenAPI.getAccessToken(CORP_ID, SECRET);
if (accessToken != null) {
return accessToken.getAccesstoken();
}
log.warn("获取AccessToken失败");
return null;
}
@Override
public boolean syncLocalDepartmentToThirdApp(String ids) {
String accessToken = this.getAccessToken();
if (accessToken == null) {
return false;
}
// 获取企业微信所有的部门
List<Department> departments = JwDepartmentAPI.getAllDepartment(accessToken);
if (departments == null) {
return false;
}
// 删除企业微信有但本地没有的部门(以本地部门数据为主)(以为企业微信不能创建同名部门,所以只能先删除)
List<JwDepartmentTreeVo> departmentTreeList = JwDepartmentTreeVo.listToTree(departments);
this.deleteDepartRecursion(departmentTreeList, accessToken, true);
// 获取本地所有部门树结构
List<SysDepartTreeModel> sysDepartsTree = sysDepartService.queryTreeList();
// -- 企业微信不能创建新的顶级部门所以新的顶级部门的parentId就为1
Department parent = new Department();
parent.setId("1");
// 递归同步部门
departments = JwDepartmentAPI.getAllDepartment(accessToken);
this.syncDepartmentRecursion(sysDepartsTree, departments, parent, accessToken);
return true;
}
// 递归删除部门以及子部门,由于企业微信不允许删除带有成员和子部门的部门,所以需要递归删除下子部门,然后把部门成员移动端根部门下
private void deleteDepartRecursion(List<JwDepartmentTreeVo> children, String accessToken, boolean ifLocal) {
for (JwDepartmentTreeVo departmentTree : children) {
String depId = departmentTree.getId();
// 过滤根部门
if (!"1".equals(depId)) {
// 判断本地是否有该部门
if (ifLocal) {
LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysDepart::getQywxIdentifier, depId);
SysDepart sysDepart = sysDepartService.getOne(queryWrapper);
// 本地有该部门,不删除
if (sysDepart != null) {
if (departmentTree.hasChildren()) {
this.deleteDepartRecursion(departmentTree.getChildren(), accessToken, true);
}
continue;
}
}
// 判断是否有成员,有就移动到根部门
List<User> departUserList = JwUserAPI.getUsersByDepartid(depId, "1", null, accessToken);
if (departUserList != null && departUserList.size() > 0) {
for (User user : departUserList) {
User updateUser = new User();
updateUser.setUserid(user.getUserid());
updateUser.setDepartment(new Integer[]{1});
JwUserAPI.updateUser(updateUser, accessToken);
}
}
// 有子部门优先删除子部门
if (departmentTree.hasChildren()) {
this.deleteDepartRecursion(departmentTree.getChildren(), accessToken, false);
}
// 执行删除操作
JwDepartmentAPI.deleteDepart(depId, accessToken);
}
}
}
// 递归同步部门到第三方APP
private void syncDepartmentRecursion(List<SysDepartTreeModel> sysDepartsTree, List<Department> departments, Department parent, String accessToken) {
if (sysDepartsTree != null && sysDepartsTree.size() != 0) {
for1:
for (SysDepartTreeModel depart : sysDepartsTree) {
for (Department department : departments) {
// id相同代表已存在执行修改操作
if (department.getId().equals(depart.getQywxIdentifier())) {
this.sysDepartToQwDepartment(depart, department, parent.getId());
JwDepartmentAPI.updateDepart(department, accessToken);
// 紧接着同步子级
this.syncDepartmentRecursion(depart.getChildren(), departments, department, accessToken);
// 跳出外部循环
continue for1;
}
}
// 循环到此说明是新部门,直接调接口创建
Department newDepartment = this.sysDepartToQwDepartment(depart, parent.getId());
DepartMsgResponse response = JwDepartmentAPI.createDepartment(newDepartment, accessToken);
// 创建成功将返回的id绑定到本地
if (response != null && response.getId() != null) {
SysDepart sysDepart = new SysDepart();
sysDepart.setId(depart.getId());
sysDepart.setQywxIdentifier(response.getId().toString());
sysDepartService.updateById(sysDepart);
Department newParent = new Department();
newParent.setId(response.getId().toString());
// 紧接着同步子级
this.syncDepartmentRecursion(depart.getChildren(), departments, newParent, accessToken);
}
// 收集错误信息
// this.syncUserCollectErrInfo(errCode, sysUser, errInfo);
}
}
}
@Override
public SyncInfoVo syncThirdAppDepartmentToLocal(String ids) {
SyncInfoVo syncInfo = new SyncInfoVo();
String accessToken = this.getAccessToken();
if (accessToken == null) {
syncInfo.addFailInfo("accessToken获取失败");
return syncInfo;
}
// 获取企业微信所有的部门
List<Department> departments = JwDepartmentAPI.getAllDepartment(accessToken);
if (departments == null) {
syncInfo.addFailInfo("企业微信部门信息获取失败!");
return syncInfo;
}
String username = JwtUtil.getUserNameByToken(SpringContextUtils.getHttpServletRequest());
// 将list转为tree
List<JwDepartmentTreeVo> departmentTreeList = JwDepartmentTreeVo.listToTree(departments);
// 递归同步部门
this.syncDepartmentToLocalRecursion(departmentTreeList, null, username, syncInfo);
return syncInfo;
}
/**
*
*/
private void syncDepartmentToLocalRecursion(List<JwDepartmentTreeVo> departmentTreeList, String sysParentId, String username, SyncInfoVo syncInfo) {
if (departmentTreeList != null && departmentTreeList.size() != 0) {
for (JwDepartmentTreeVo departmentTree : departmentTreeList) {
String depId = departmentTree.getId();
LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
// 根据 qywxIdentifier 字段查询
queryWrapper.eq(SysDepart::getQywxIdentifier, depId);
SysDepart sysDepart = sysDepartService.getOne(queryWrapper);
if (sysDepart != null) {
// 执行更新操作
SysDepart updateSysDepart = this.qwDepartmentToSysDepart(departmentTree, sysDepart);
if (sysParentId != null) {
updateSysDepart.setParentId(sysParentId);
}
try {
sysDepartService.updateDepartDataById(updateSysDepart, username);
String str = String.format("部门 %s 更新成功!", updateSysDepart.getDepartName());
syncInfo.addSuccessInfo(str);
} catch (Exception e) {
this.syncDepartCollectErrInfo(e, departmentTree, syncInfo);
}
if (departmentTree.hasChildren()) {
// 紧接着同步子级
this.syncDepartmentToLocalRecursion(departmentTree.getChildren(), updateSysDepart.getId(), username, syncInfo);
}
} else {
// 执行新增操作
SysDepart newSysDepart = this.qwDepartmentToSysDepart(departmentTree, null);
if (sysParentId != null) {
newSysDepart.setParentId(sysParentId);
}
try {
sysDepartService.saveDepartData(newSysDepart, username);
String str = String.format("部门 %s 创建成功!", newSysDepart.getDepartName());
syncInfo.addSuccessInfo(str);
} catch (Exception e) {
this.syncDepartCollectErrInfo(e, departmentTree, syncInfo);
}
// 紧接着同步子级
if (departmentTree.hasChildren()) {
this.syncDepartmentToLocalRecursion(departmentTree.getChildren(), newSysDepart.getId(), username, syncInfo);
}
}
}
}
}
@Override
public SyncInfoVo syncLocalUserToThirdApp(String ids) {
SyncInfoVo syncInfo = new SyncInfoVo();
String accessToken = this.getAccessToken();
if (accessToken == null) {
syncInfo.addFailInfo("accessToken获取失败");
return syncInfo;
}
// 获取企业微信所有的用户
List<User> qwUsers = JwUserAPI.getDetailUsersByDepartid("1", null, null, accessToken);
if (qwUsers == null) {
syncInfo.addFailInfo("企业微信用户列表查询失败!");
return syncInfo;
}
List<SysUser> sysUsers;
if (StringUtils.isNotBlank(ids)) {
String[] idList = ids.split(",");
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SysUser::getId, (Object[]) idList);
// 获取本地指定用户
sysUsers = sysUserService.list(queryWrapper);
} else {
// 获取本地所有用户
sysUsers = sysUserService.list();
}
// 循环判断新用户和需要更新的用户
for1:
for (SysUser sysUser : sysUsers) {
// 外部模拟登陆临时账号,不同步
if ("_reserve_user_external".equals(sysUser.getUsername())) {
continue;
}
/*
*
* 1. sys_third_account
* 2. username
*/
User qwUser;
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneBySysUserId(sysUser.getId(), ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
for (User qwUserTemp : qwUsers) {
if (sysThirdAccount == null || oConvertUtils.isEmpty(sysThirdAccount.getThirdUserId()) || !sysThirdAccount.getThirdUserId().equals(qwUserTemp.getUserid())) {
// sys_third_account 表匹配失败,尝试用手机号匹配
String phone = sysUser.getPhone();
if (!(oConvertUtils.isEmpty(phone) || phone.equals(qwUserTemp.getMobile()))) {
// 手机号匹配失败再尝试用username匹配
String username = sysUser.getUsername();
if (!(oConvertUtils.isEmpty(username) || username.equals(qwUserTemp.getUserid()))) {
// username 匹配失败,直接跳到下一次循环继续
continue;
}
}
}
// 循环到此说明用户匹配成功,进行更新操作
qwUser = this.sysUserToQwUser(sysUser, qwUserTemp);
int errCode = JwUserAPI.updateUser(qwUser, accessToken);
// 收集错误信息
this.syncUserCollectErrInfo(errCode, sysUser, syncInfo);
this.thirdAccountSaveOrUpdate(sysThirdAccount, sysUser.getId(), qwUser.getUserid());
// 更新完成,直接跳到下一次外部循环继续
continue for1;
}
// 循环到此说明是新用户,直接调接口创建
qwUser = this.sysUserToQwUser(sysUser);
int errCode = JwUserAPI.createUser(qwUser, accessToken);
// 收集错误信息
boolean apiSuccess = this.syncUserCollectErrInfo(errCode, sysUser, syncInfo);
if (apiSuccess) {
this.thirdAccountSaveOrUpdate(sysThirdAccount, sysUser.getId(), qwUser.getUserid());
}
}
return syncInfo;
}
@Override
public SyncInfoVo syncThirdAppUserToLocal() {
SyncInfoVo syncInfo = new SyncInfoVo();
String accessToken = this.getAccessToken();
if (accessToken == null) {
syncInfo.addFailInfo("accessToken获取失败");
return syncInfo;
}
// 获取企业微信所有的用户
List<User> qwUsersList = JwUserAPI.getDetailUsersByDepartid("1", null, null, accessToken);
if (qwUsersList == null) {
syncInfo.addFailInfo("企业微信用户列表查询失败!");
return syncInfo;
}
//查询本地用户
List<SysUser> sysUsersList = sysUserService.list();
// 循环判断新用户和需要更新的用户
for (User qwUser : qwUsersList) {
/*
*
* 1. sys_third_account
* 2. username
*/
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneByThirdUserId(qwUser.getUserid(), ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
List<SysUser> collect = sysUsersList.stream().filter(user -> (qwUser.getMobile().equals(user.getPhone()) || qwUser.getUserid().equals(user.getUsername()))
).collect(Collectors.toList());
if (collect != null && collect.size() > 0) {
SysUser sysUserTemp = collect.get(0);
// 循环到此说明用户匹配成功,进行更新操作
SysUser updateSysUser = this.qwUserToSysUser(qwUser, sysUserTemp);
try {
sysUserService.updateById(updateSysUser);
String str = String.format("用户 %s(%s) 更新成功!", updateSysUser.getRealname(), updateSysUser.getUsername());
syncInfo.addSuccessInfo(str);
} catch (Exception e) {
this.syncUserCollectErrInfo(e, qwUser, syncInfo);
}
this.thirdAccountSaveOrUpdate(sysThirdAccount, updateSysUser.getId(), qwUser.getUserid());
// 更新完成,直接跳到下一次外部循环继续
}else{
// 没匹配到用户则走新增逻辑
SysUser newSysUser = this.qwUserToSysUser(qwUser);
try {
sysUserService.save(newSysUser);
String str = String.format("用户 %s(%s) 创建成功!", newSysUser.getRealname(), newSysUser.getUsername());
syncInfo.addSuccessInfo(str);
} catch (Exception e) {
this.syncUserCollectErrInfo(e, qwUser, syncInfo);
}
this.thirdAccountSaveOrUpdate(sysThirdAccount, newSysUser.getId(), qwUser.getUserid());
}
}
return syncInfo;
}
/**
*
*
* @param sysThirdAccount null
* @param sysUserId ID
* @param qwUserId ID
*/
private void thirdAccountSaveOrUpdate(SysThirdAccount sysThirdAccount, String sysUserId, String qwUserId) {
if (sysThirdAccount == null) {
sysThirdAccount = new SysThirdAccount();
sysThirdAccount.setSysUserId(sysUserId);
sysThirdAccount.setStatus(1);
sysThirdAccount.setDelFlag(0);
sysThirdAccount.setThirdType(ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
}
sysThirdAccount.setThirdUserId(qwUserId);
sysThirdAccountService.saveOrUpdate(sysThirdAccount);
}
/**
*
*/
private boolean syncUserCollectErrInfo(int errCode, SysUser sysUser, SyncInfoVo syncInfo) {
if (errCode != 0) {
String msg = "";
// https://open.work.weixin.qq.com/api/doc/90000/90139/90313
switch (errCode) {
case 40003:
msg = "无效的UserID";
break;
case 60129:
msg = "手机和邮箱不能都为空";
break;
case 60102:
msg = "UserID已存在";
break;
case 60103:
msg = "手机号码不合法";
break;
case 60104:
msg = "手机号码已存在";
break;
}
String str = String.format("用户 %s(%s) 同步失败!错误码:%s——%s", sysUser.getUsername(), sysUser.getRealname(), errCode, msg);
syncInfo.addFailInfo(str);
return false;
} else {
String str = String.format("用户 %s(%s) 同步成功!", sysUser.getUsername(), sysUser.getRealname());
syncInfo.addSuccessInfo(str);
return true;
}
}
private boolean syncUserCollectErrInfo(Exception e, User qwUser, SyncInfoVo syncInfo) {
String msg;
if (e instanceof DuplicateKeyException) {
msg = e.getCause().getMessage();
} else {
msg = e.getMessage();
}
String str = String.format("用户 %s(%s) 同步失败!错误信息:%s", qwUser.getUserid(), qwUser.getName(), msg);
syncInfo.addFailInfo(str);
return false;
}
private boolean syncDepartCollectErrInfo(Exception e, Department department, SyncInfoVo syncInfo) {
String msg;
if (e instanceof DuplicateKeyException) {
msg = e.getCause().getMessage();
} else {
msg = e.getMessage();
}
String str = String.format("部门 %s(%s) 同步失败!错误信息:%s", department.getName(), department.getId(), msg);
syncInfo.addFailInfo(str);
return false;
}
/**
* SysUserUser
*/
private User sysUserToQwUser(SysUser sysUser) {
User user = new User();
// 通过 username 来关联
user.setUserid(sysUser.getUsername());
return this.sysUserToQwUser(sysUser, user);
}
/**
* SysUserUser
*/
private User sysUserToQwUser(SysUser sysUser, User user) {
user.setName(sysUser.getRealname());
user.setMobile(sysUser.getPhone());
// 查询并同步用户部门关系
List<SysDepart> departList = this.getUserDepart(sysUser);
if (departList != null) {
List<Integer> departmentIdList = new ArrayList<>();
// 企业微信 1表示为上级0表示非上级
List<Integer> isLeaderInDept = new ArrayList<>();
// 当前用户管理的部门
List<String> manageDepartIdList = new ArrayList<>();
if (oConvertUtils.isNotEmpty(sysUser.getDepartIds())) {
manageDepartIdList = Arrays.asList(sysUser.getDepartIds().split(","));
}
for (SysDepart sysDepart : departList) {
// 企业微信的部门id
if (oConvertUtils.isNotEmpty(sysDepart.getQywxIdentifier())) {
try {
departmentIdList.add(Integer.parseInt(sysDepart.getQywxIdentifier()));
} catch (NumberFormatException ignored) {
continue;
}
// 判断用户身份,是否为上级
if (CommonConstant.USER_IDENTITY_2.equals(sysUser.getUserIdentity())) {
// 判断当前部门是否为该用户管理的部门
isLeaderInDept.add(manageDepartIdList.contains(sysDepart.getId()) ? 1 : 0);
} else {
isLeaderInDept.add(0);
}
}
}
user.setDepartment(departmentIdList.toArray(new Integer[]{}));
// 个数必须和参数department的个数一致表示在所在的部门内是否为上级。1表示为上级0表示非上级。在审批等应用里可以用来标识上级审批人
user.setIs_leader_in_dept(isLeaderInDept.toArray(new Integer[]{}));
}
if (user.getDepartment() == null || user.getDepartment().length == 0) {
// 没有找到匹配部门,同步到根部门下
user.setDepartment(new Integer[]{1});
user.setIs_leader_in_dept(new Integer[]{0});
}
// 职务翻译
if (oConvertUtils.isNotEmpty(sysUser.getPost())) {
SysPosition position = sysPositionService.getByCode(sysUser.getPost());
if (position != null) {
user.setPosition(position.getName());
}
}
if (sysUser.getSex() != null) {
user.setGender(sysUser.getSex().toString());
}
user.setEmail(sysUser.getEmail());
// 启用/禁用成员(状态),规则不同,需要转换
// 企业微信规则1表示启用成员0表示禁用成员
// JEECG规则1正常2冻结
if (sysUser.getStatus() != null) {
if (sysUser.getStatus() == 1 || sysUser.getStatus() == 2) {
user.setEnable(sysUser.getStatus() == 1 ? 1 : 0);
} else {
user.setEnable(1);
}
}
user.setTelephone(sysUser.getTelephone());// 座机号
// --- 企业微信没有逻辑删除的功能
// update-begin--Author:sunjianlei Date:20210520 for本地逻辑删除的用户在企业微信里禁用 -----
if (CommonConstant.DEL_FLAG_1.equals(sysUser.getDelFlag())) {
user.setEnable(0);
}
// update-end--Author:sunjianlei Date:20210520 for本地逻辑删除的用户在企业微信里冻结 -----
return user;
}
/**
*
*/
private List<SysDepart> getUserDepart(SysUser sysUser) {
// 根据用户部门关系表查询出用户的部门
LambdaQueryWrapper<SysUserDepart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUserDepart::getUserId, sysUser.getId());
List<SysUserDepart> sysUserDepartList = sysUserDepartService.list(queryWrapper);
if (sysUserDepartList.size() == 0) {
return null;
}
// 根据用户部门
LambdaQueryWrapper<SysDepart> departQueryWrapper = new LambdaQueryWrapper<>();
List<String> departIdList = sysUserDepartList.stream().map(SysUserDepart::getDepId).collect(Collectors.toList());
departQueryWrapper.in(SysDepart::getId, departIdList);
List<SysDepart> departList = sysDepartService.list(departQueryWrapper);
return departList.size() == 0 ? null : departList;
}
/**
* UserSysUser
*/
private SysUser qwUserToSysUser(User user) {
SysUser sysUser = new SysUser();
sysUser.setDelFlag(0);
// 通过 username 来关联
sysUser.setUsername(user.getUserid());
// 密码默认为 “123456”随机加盐
String password = "123456", salt = oConvertUtils.randomGen(8);
String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), password, salt);
sysUser.setSalt(salt);
sysUser.setPassword(passwordEncode);
return this.qwUserToSysUser(user, sysUser);
}
/**
* UserSysUser
*/
private SysUser qwUserToSysUser(User qwUser, SysUser oldSysUser) {
SysUser sysUser = new SysUser();
BeanUtils.copyProperties(oldSysUser, sysUser);
sysUser.setRealname(qwUser.getName());
sysUser.setPost(qwUser.getPosition());
try {
sysUser.setSex(Integer.parseInt(qwUser.getGender()));
} catch (NumberFormatException ignored) {
}
// 因为唯一键约束的原因,如果原数据和旧数据相同,就不更新
if (oConvertUtils.isNotEmpty(qwUser.getEmail()) && !qwUser.getEmail().equals(sysUser.getEmail())) {
sysUser.setEmail(qwUser.getEmail());
} else {
sysUser.setEmail(null);
}
// 因为唯一键约束的原因,如果原数据和旧数据相同,就不更新
if (oConvertUtils.isNotEmpty(qwUser.getMobile()) && !qwUser.getMobile().equals(sysUser.getPhone())) {
sysUser.setPhone(qwUser.getMobile());
} else {
sysUser.setPhone(null);
}
// 启用/禁用成员(状态),规则不同,需要转换
// 企业微信规则1表示启用成员0表示禁用成员
// JEECG规则1正常2冻结
if (qwUser.getEnable() != null) {
sysUser.setStatus(qwUser.getEnable() == 1 ? 1 : 2);
}
sysUser.setTelephone(qwUser.getTelephone());// 座机号
// --- 企业微信没有逻辑删除的功能
// sysUser.setDelFlag()
return sysUser;
}
/**
* SysDepartTreeModelDepartment
*/
private Department sysDepartToQwDepartment(SysDepartTreeModel departTree, String parentId) {
Department department = new Department();
return this.sysDepartToQwDepartment(departTree, department, parentId);
}
/**
* SysDepartTreeModelDepartment
*/
private Department sysDepartToQwDepartment(SysDepartTreeModel departTree, Department department, String parentId) {
department.setName(departTree.getDepartName());
department.setParentid(parentId);
if (departTree.getDepartOrder() != null) {
department.setOrder(departTree.getDepartOrder().toString());
}
return department;
}
/**
* DepartmentSysDepart
*/
private SysDepart qwDepartmentToSysDepart(Department department, SysDepart oldSysDepart) {
SysDepart sysDepart = new SysDepart();
if (oldSysDepart != null) {
BeanUtils.copyProperties(oldSysDepart, sysDepart);
}
sysDepart.setQywxIdentifier(department.getId());
sysDepart.setDepartName(department.getName());
try {
sysDepart.setDepartOrder(Integer.parseInt(department.getOrder()));
} catch (NumberFormatException ignored) {
}
return sysDepart;
}
@Override
public int removeThirdAppUser(List<String> userIdList) {
// 判断启用状态
if (!thirdAppConfig.isWechatEnterpriseEnabled()) {
return -1;
}
int count = 0;
if (userIdList != null && userIdList.size() > 0) {
String accessToken = this.getAccessToken();
if (accessToken == null) {
return count;
}
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysThirdAccount::getThirdType, ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
queryWrapper.in(SysThirdAccount::getSysUserId, userIdList);
// 根据userId获取第三方用户的id
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.list(queryWrapper);
List<String> thirdUserIdList = thirdAccountList.stream().map(SysThirdAccount::getThirdUserId).collect(Collectors.toList());
for (String thirdUserId : thirdUserIdList) {
if (oConvertUtils.isNotEmpty(thirdUserId)) {
// 没有批量删除的接口
int err = JwUserAPI.deleteUser(thirdUserId, accessToken);
if (err == 0) {
count++;
}
}
}
}
return count;
}
@Override
public boolean sendMessage(MessageDTO message) {
return this.sendMessage(message, false);
}
@Override
public boolean sendMessage(MessageDTO message, boolean verifyConfig) {
JSONObject response = this.sendMessageResponse(message, verifyConfig);
if (response != null) {
return response.getIntValue("errcode") == 0;
}
return false;
}
public JSONObject sendMessageResponse(MessageDTO message, boolean verifyConfig) {
if (verifyConfig && !thirdAppConfig.isWechatEnterpriseEnabled()) {
return null;
}
String accessToken = this.getAppAccessToken();
if (accessToken == null) {
return null;
}
Text text = new Text();
text.setMsgtype("text");
text.setTouser(this.getTouser(message.getToUser(), message.isToAll()));
TextEntity entity = new TextEntity();
entity.setContent(message.getContent());
text.setText(entity);
text.setAgentid(thirdAppConfig.getWechatEnterprise().getAgentIdInt());
return JwMessageAPI.sendTextMessage(text, accessToken);
}
/**
* SysAnnouncement
*
* @param announcement
* @param verifyConfig APP
* @return
*/
public JSONObject sendTextCardMessage(SysAnnouncement announcement, boolean verifyConfig) {
if (verifyConfig && !thirdAppConfig.isWechatEnterpriseEnabled()) {
return null;
}
String accessToken = this.getAppAccessToken();
if (accessToken == null) {
return null;
}
TextCard textCard = new TextCard();
textCard.setAgentid(thirdAppConfig.getWechatEnterprise().getAgentIdInt());
boolean isToAll = CommonConstant.MSG_TYPE_ALL.equals(announcement.getMsgType());
String usernameString = "";
if (!isToAll) {
// 将userId转为username
String userId = announcement.getUserIds();
String[] userIds = null;
if(oConvertUtils.isNotEmpty(userId)){
userIds = userId.substring(0, (userId.length() - 1)).split(",");
}else{
LambdaQueryWrapper<SysAnnouncementSend> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysAnnouncementSend::getAnntId, announcement.getId());
SysAnnouncementSend sysAnnouncementSend = sysAnnouncementSendMapper.selectOne(queryWrapper);
userIds = new String[] {sysAnnouncementSend.getUserId()};
}
List<String> usernameList = sysUserService.userIdToUsername(Arrays.asList(userIds));
usernameString = String.join(",", usernameList);
}
textCard.setTouser(this.getTouser(usernameString, isToAll));
TextCardEntity entity = new TextCardEntity();
entity.setTitle(announcement.getTitile());
entity.setDescription(oConvertUtils.getString(announcement.getMsgAbstract(),"空"));
entity.setUrl(RestUtil.getBaseUrl() + "/sys/annountCement/show/" + announcement.getId());
textCard.setTextcard(entity);
return JwMessageAPI.sendTextCardMessage(textCard, accessToken);
}
private String getTouser(String origin, boolean toAll) {
if (toAll) {
return "@all";
} else {
String[] toUsers = origin.split(",");
// 通过第三方账号表查询出第三方userId
List<SysThirdAccount> thirdAccountList = sysThirdAccountService.listThirdUserIdByUsername(toUsers, ThirdAppConfig.WECHAT_ENTERPRISE.toLowerCase());
List<String> toUserList = thirdAccountList.stream().map(SysThirdAccount::getThirdUserId).collect(Collectors.toList());
// 多个接收者用‘|’分隔
return String.join("|", toUserList);
}
}
}

View File

@ -0,0 +1,52 @@
package org.jeecg.modules.system.service.impl.desform;
import org.jeecg.common.api.desform.ISysTranslateAPI;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.modules.system.service.ISysCategoryService;
import org.jeecg.modules.system.service.ISysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* APIsystem
*
* @author sunjianlei
*/
@Component
public class SysTranslateAPIImpl implements ISysTranslateAPI {
@Autowired
ISysCategoryService sysCategoryService;
@Autowired
ISysDictService sysDictService;
@Override
public List<String> categoryLoadDictItem(String ids) {
return sysCategoryService.loadDictItem(ids, false);
}
@Override
public List<String> dictLoadDictItem(String dictCode, String keys) {
String[] params = dictCode.split(",");
return sysDictService.queryTableDictByKeys(params[0], params[1], params[2], keys, false);
}
@Override
public List<DictModel> dictGetDictItems(String dictCode) {
List<DictModel> ls = sysDictService.getDictItems(dictCode);
if (ls == null) {
ls = new ArrayList<>();
}
return ls;
}
@Override
public List<DictModel> dictLoadDict(String dictCode, String keyword, Integer pageSize) {
return sysDictService.loadDict(dictCode, keyword, pageSize);
}
}

View File

@ -1,25 +1,25 @@
package org.jeecg.modules.system.util;
import lombok.extern.slf4j.Slf4j;
/**
* tenant_id
*/
@Slf4j
public class TenantContext {
private static ThreadLocal<String> currentTenant = new ThreadLocal<>();
public static void setTenant(String tenant) {
log.debug(" setting tenant to " + tenant);
currentTenant.set(tenant);
}
public static String getTenant() {
return currentTenant.get();
}
public static void clear(){
currentTenant.remove();
}
}
//package org.jeecg.modules.system.util;
//
//import lombok.extern.slf4j.Slf4j;
//
///**
// * 多租户 tenant_id存储器
// */
//@Slf4j
//public class TenantContext {
//
// private static ThreadLocal<String> currentTenant = new ThreadLocal<>();
//
// public static void setTenant(String tenant) {
// log.debug(" setting tenant to " + tenant);
// currentTenant.set(tenant);
// }
//
// public static String getTenant() {
// return currentTenant.get();
// }
//
// public static void clear(){
// currentTenant.remove();
// }
//}

View File

@ -0,0 +1,76 @@
package org.jeecg.modules.system.vo.thirdapp;
import com.jeecg.dingtalk.api.department.vo.Department;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @author sunjianlei
*/
public class JdtDepartmentTreeVo extends Department {
private List<JdtDepartmentTreeVo> children;
public List<JdtDepartmentTreeVo> getChildren() {
return children;
}
public JdtDepartmentTreeVo setChildren(List<JdtDepartmentTreeVo> children) {
this.children = children;
return this;
}
public JdtDepartmentTreeVo(Department department) {
BeanUtils.copyProperties(department, this);
}
/**
*
*/
public boolean hasChildren() {
return children != null && children.size() > 0;
}
@Override
public String toString() {
return "JwDepartmentTree{" +
"children=" + children +
"} " + super.toString();
}
/**
* listtree
*/
public static List<JdtDepartmentTreeVo> listToTree(List<Department> allDepartment) {
// 先找出所有的父级
List<JdtDepartmentTreeVo> treeList = getByParentId(1, allDepartment);
getChildrenRecursion(treeList, allDepartment);
return treeList;
}
private static List<JdtDepartmentTreeVo> getByParentId(Integer parentId, List<Department> allDepartment) {
List<JdtDepartmentTreeVo> list = new ArrayList<>();
for (Department department : allDepartment) {
if (parentId.equals(department.getParent_id())) {
list.add(new JdtDepartmentTreeVo(department));
}
}
return list;
}
private static void getChildrenRecursion(List<JdtDepartmentTreeVo> treeList, List<Department> allDepartment) {
for (JdtDepartmentTreeVo departmentTree : treeList) {
// 递归寻找子级
List<JdtDepartmentTreeVo> children = getByParentId(departmentTree.getDept_id(), allDepartment);
if (children.size() > 0) {
departmentTree.setChildren(children);
getChildrenRecursion(children, allDepartment);
}
}
}
}

View File

@ -0,0 +1,76 @@
package org.jeecg.modules.system.vo.thirdapp;
import com.jeecg.qywx.api.department.vo.Department;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @author sunjianlei
*/
public class JwDepartmentTreeVo extends Department {
private List<JwDepartmentTreeVo> children;
public List<JwDepartmentTreeVo> getChildren() {
return children;
}
public JwDepartmentTreeVo setChildren(List<JwDepartmentTreeVo> children) {
this.children = children;
return this;
}
public JwDepartmentTreeVo(Department department) {
BeanUtils.copyProperties(department, this);
}
/**
*
*/
public boolean hasChildren() {
return children != null && children.size() > 0;
}
@Override
public String toString() {
return "JwDepartmentTree{" +
"children=" + children +
"} " + super.toString();
}
/**
* listtree
*/
public static List<JwDepartmentTreeVo> listToTree(List<Department> allDepartment) {
// 先找出所有的父级
List<JwDepartmentTreeVo> treeList = getByParentId("1", allDepartment);
getChildrenRecursion(treeList, allDepartment);
return treeList;
}
private static List<JwDepartmentTreeVo> getByParentId(String parentId, List<Department> allDepartment) {
List<JwDepartmentTreeVo> list = new ArrayList<>();
for (Department department : allDepartment) {
if (parentId.equals(department.getParentid())) {
list.add(new JwDepartmentTreeVo(department));
}
}
return list;
}
private static void getChildrenRecursion(List<JwDepartmentTreeVo> treeList, List<Department> allDepartment) {
for (JwDepartmentTreeVo departmentTree : treeList) {
// 递归寻找子级
List<JwDepartmentTreeVo> children = getByParentId(departmentTree.getId(), allDepartment);
if (children.size() > 0) {
departmentTree.setChildren(children);
getChildrenRecursion(children, allDepartment);
}
}
}
}

View File

@ -0,0 +1,44 @@
package org.jeecg.modules.system.vo.thirdapp;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @author sunjianlei
*/
@Data
public class SyncInfoVo {
/**
*
*/
private List<String> successInfo;
/**
*
*/
private List<String> failInfo;
public SyncInfoVo() {
this.successInfo = new ArrayList<>();
this.failInfo = new ArrayList<>();
}
public SyncInfoVo(List<String> successInfo, List<String> failInfo) {
this.successInfo = successInfo;
this.failInfo = failInfo;
}
public SyncInfoVo addSuccessInfo(String info) {
this.successInfo.add(info);
return this;
}
public SyncInfoVo addFailInfo(String info) {
this.failInfo.add(info);
return this;
}
}

View File

@ -14,16 +14,16 @@ server:
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
management:
endpoints:
web:
exposure:
include: metrics,httptrace
endpoints:
web:
exposure:
include: metrics,httptrace
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
multipart:
max-file-size: 10MB
max-request-size: 10MB
mail:
host: smtp.163.com
username: jeecgos@163.com
@ -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
@ -147,7 +147,7 @@ spring:
host: 127.0.0.1
lettuce:
pool:
max-active: 8 #最大连接数据库连接数,设 0 为没有限制
max-active: 8 #最大连接数据库连接数,设 -1 为没有限制
max-idle: 8 #最大等待连接中的数量,设 0 为没有限制
max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
@ -170,29 +170,27 @@ mybatis-plus:
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 返回类型为Map,显示null对应的字段
call-setters-on-nulls: true
#minidao 设
#jeecg专用配
minidao :
base-package: org.jeecg.modules.jmreport.*
#DB类型mysql | postgresql | oracle | sqlserver
#DB类型mysql | postgresql | oracle | sqlserver| other
db-type: mysql
#jeecg专用配置
jeecg :
# 本地local\Miniominio\阿里云alioss
uploadType: local
path :
#文件上传根目录 设置
upload: D://opt//upFiles
upload: /opt/upFiles
#webapp文件路径
webapp: D://opt//webapp
webapp: /opt/webapp
shiro:
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**
#阿里云oss存储配置
#阿里云oss存储和大鱼短信秘钥配置
oss:
endpoint: oss-cn-beijing.aliyuncs.com
accessKey: ??
secretKey: ??
endpoint: oss-cn-beijing.aliyuncs.com
bucketName: ??
staticDomain: ??
# ElasticSearch 6设置
elasticsearch:
cluster-name: jeecg-ES
@ -204,6 +202,9 @@ jeecg :
theme-color: "#1890ff"
# 文件、图片上传方式可选项qiniu七牛云、system跟随系统配置
upload-type: system
map:
# 配置百度地图的AK申请地址https://lbs.baidu.com/apiconsole/key?application=key#/home
baidu: ??
# 在线预览文件服务器地址配置
file-view-domain: 127.0.0.1:8012
# minio文件上传
@ -218,7 +219,7 @@ jeecg :
#数据字典是否进行saas数据隔离自己看自己的字典
saas: false
#是否需要校验token
is_verify_token: false
is_verify_token: true
#必须校验方法
verify_methods: remove,delete,save,add,update
#Wps在线文档
@ -260,7 +261,7 @@ logging:
knife4j:
production: false
basic:
enable: false
enable: true
username: jeecg
password: jeecg1314
#第三方登录
@ -275,7 +276,7 @@ justauth:
client-id: ??
client-secret: ??
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_enterprise/callback
agent-id: 1000002
agent-id: ??
DINGTALK:
client-id: ??
client-secret: ??
@ -288,3 +289,26 @@ justauth:
type: default
prefix: 'demo::'
timeout: 1h
#第三方APP对接
third-app:
enabled: false
type:
#企业微信
WECHAT_ENTERPRISE:
enabled: false
#CORP_ID
client-id: ??
#SECRET
client-secret: ??
#自建应用id
agent-id: ??
#自建应用秘钥(新版企微需要配置)
# agent-app-secret: ??
#钉钉
DINGTALK:
enabled: false
# appKey
client-id: ??
# appSecret
client-secret: ??
agent-id: ??

View File

@ -14,16 +14,16 @@ server:
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
management:
endpoints:
web:
exposure:
include: metrics,httptrace
endpoints:
web:
exposure:
include: metrics,httptrace
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
multipart:
max-file-size: 10MB
max-request-size: 10MB
mail:
host: smtp.163.com
username: jeecgos@163.com
@ -147,7 +147,7 @@ spring:
host: 127.0.0.1
lettuce:
pool:
max-active: 8 #最大连接数据库连接数,设 0 为没有限制
max-active: 8 #最大连接数据库连接数,设 -1 为没有限制
max-idle: 8 #最大等待连接中的数量,设 0 为没有限制
max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
@ -170,12 +170,11 @@ mybatis-plus:
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 返回类型为Map,显示null对应的字段
call-setters-on-nulls: true
#minidao 设
#jeecg专用配
minidao :
base-package: org.jeecg.modules.jmreport.*
#DB类型mysql | postgresql | oracle | sqlserver
#DB类型mysql | postgresql | oracle | sqlserver| other
db-type: mysql
#jeecg专用配置
jeecg :
# 本地local\Miniominio\阿里云alioss
uploadType: alioss
@ -185,18 +184,18 @@ jeecg :
#webapp文件路径
webapp: /opt/jeecg-boot/webapp
shiro:
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**
#阿里云oss存储配置
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**,/api/getUserInfo
#阿里云oss存储和大鱼短信秘钥配置
oss:
endpoint: oss-cn-beijing.aliyuncs.com
accessKey: ??
secretKey: ??
endpoint: oss-cn-beijing.aliyuncs.com
bucketName: ??
staticDomain: https://static.jeecg.com
# ElasticSearch 设置
elasticsearch:
cluster-name: jeecg-ES
cluster-nodes: 111.225.222.176:9200
cluster-nodes: ??
check-enabled: true
# 表单设计器配置
desform:
@ -204,6 +203,9 @@ jeecg :
theme-color: "#1890ff"
# 文件、图片上传方式可选项qiniu七牛云、system跟随系统配置
upload-type: system
map:
# 配置百度地图的AK申请地址https://lbs.baidu.com/apiconsole/key?application=key#/home
baidu: ??
# 在线预览文件服务器地址配置
file-view-domain: http://fileview.jeecg.com
# minio文件上传
@ -211,7 +213,7 @@ jeecg :
minio_url: http://minio.jeecg.com
minio_name: ??
minio_pass: ??
bucketName: otatest
bucketName: ??
#大屏报表参数设置
jmreport:
mode: prod
@ -275,7 +277,7 @@ justauth:
client-id: ??
client-secret: ??
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_enterprise/callback
agent-id: 1000002
agent-id: ??
DINGTALK:
client-id: ??
client-secret: ??
@ -287,4 +289,27 @@ justauth:
cache:
type: default
prefix: 'demo::'
timeout: 1h
timeout: 1h
#第三方APP对接
third-app:
enabled: false
type:
#企业微信
WECHAT_ENTERPRISE:
enabled: false
#CORP_ID
client-id: ??
#SECRET
client-secret: ??
#自建应用id
agent-id: ??
#自建应用秘钥(新版企微需要配置)
# agent-app-secret: ??
#钉钉
DINGTALK:
enabled: false
# appKey
client-id: ??
# appSecret
client-secret: ??
agent-id: ??

View File

@ -14,16 +14,16 @@ server:
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
management:
endpoints:
web:
exposure:
include: metrics,httptrace
endpoints:
web:
exposure:
include: metrics,httptrace
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
multipart:
max-file-size: 10MB
max-request-size: 10MB
mail:
host: smtp.163.com
username: jeecgos@163.com
@ -147,7 +147,7 @@ spring:
host: 192.168.1.199
lettuce:
pool:
max-active: 8 #最大连接数据库连接数,设 0 为没有限制
max-active: 8 #最大连接数据库连接数,设 -1 为没有限制
max-idle: 8 #最大等待连接中的数量,设 0 为没有限制
max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
@ -170,12 +170,11 @@ mybatis-plus:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 返回类型为Map,显示null对应的字段
call-setters-on-nulls: true
#minidao 设
#jeecg专用配
minidao :
base-package: org.jeecg.modules.jmreport.*
#DB类型mysql | postgresql | oracle | sqlserver
#DB类型mysql | postgresql | oracle | sqlserver| other
db-type: mysql
#jeecg专用配置
jeecg :
# 本地local\Miniominio\阿里云alioss
uploadType: local
@ -186,17 +185,17 @@ jeecg :
webapp: D://opt//webapp
shiro:
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**
#阿里云oss存储配置
#阿里云oss存储和大鱼短信秘钥配置
oss:
endpoint: oss-cn-beijing.aliyuncs.com
accessKey: ??
secretKey: ??
endpoint: oss-cn-beijing.aliyuncs.com
bucketName: ??
staticDomain: https://static.jeecg.com
# ElasticSearch 设置
elasticsearch:
cluster-name: jeecg-ES
cluster-nodes: http://fileview.jeecg.com
cluster-nodes: ??
check-enabled: false
# 表单设计器配置
desform:
@ -204,6 +203,9 @@ jeecg :
theme-color: "#1890ff"
# 文件、图片上传方式可选项qiniu七牛云、system跟随系统配置
upload-type: system
map:
# 配置百度地图的AK申请地址https://lbs.baidu.com/apiconsole/key?application=key#/home
baidu: ??
# 在线预览文件服务器地址配置
file-view-domain: http://127.0.0.1:8012
# minio文件上传
@ -211,7 +213,7 @@ jeecg :
minio_url: http://minio.jeecg.com
minio_name: ??
minio_pass: ??
bucketName: otatest
bucketName: ??
#大屏报表参数设置
jmreport:
mode: prod
@ -260,7 +262,7 @@ cas:
knife4j:
production: false
basic:
enable: false
enable: true
username: jeecg
password: jeecg1314
#第三方登录
@ -275,7 +277,7 @@ justauth:
client-id: ??
client-secret: ??
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_enterprise/callback
agent-id: 1000002
agent-id: ??
DINGTALK:
client-id: ??
client-secret: ??
@ -288,3 +290,26 @@ justauth:
type: default
prefix: 'demo::'
timeout: 1h
#第三方APP对接
third-app:
enabled: false
type:
#企业微信
WECHAT_ENTERPRISE:
enabled: false
#CORP_ID
client-id: ??
#SECRET
client-secret: ??
#自建应用id
agent-id: ??
#自建应用秘钥(新版企微需要配置)
# agent-app-secret: ??
#钉钉
DINGTALK:
enabled: false
# appKey
client-id: ??
# appSecret
client-secret: ??
agent-id: ??

View File

@ -9,6 +9,6 @@ ${AnsiColor.BRIGHT_BLUE}
${AnsiColor.BRIGHT_GREEN}
Jeecg Boot Version: 2.4.3
Jeecg Boot Version: 2.4.5
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version}
${AnsiColor.BLACK}

View File

@ -45,6 +45,8 @@ public class ${entityName} implements Serializable {
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
</#if>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
</#if>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>

View File

@ -50,7 +50,7 @@
<#elseif po.classType=='pca'>
<#if query_field_no gt 1> </#if><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
<#elseif po.classType=='popup'>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')"/>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
@ -289,7 +289,7 @@
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : ''),
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
<#if list_need_category>

View File

@ -44,6 +44,7 @@
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"
<#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_depart'>

View File

@ -39,6 +39,8 @@ public class ${entityName} implements Serializable {
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
</#if>
</#if>
/**${po.filedComment}*/

View File

@ -40,6 +40,8 @@ public class ${subTab.entityName} implements Serializable {
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
</#if>
</#if>
/**${po.filedComment}*/

View File

@ -47,7 +47,7 @@
<#elseif po.classType=='pca'>
<#if query_field_no gt 1> </#if><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
<#elseif po.classType=='popup'>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')"/>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
@ -277,7 +277,7 @@
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
<#if list_need_category>

View File

@ -49,6 +49,7 @@
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"
<#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_depart'>

View File

@ -46,6 +46,7 @@
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"/>
<#elseif po.classType =='sel_depart'>
<j-select-depart v-model="model.${po.fieldName}" multi/>

View File

@ -40,6 +40,8 @@ public class ${entityName} implements Serializable {
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
</#if>
</#if>
/**${po.filedComment}*/

View File

@ -35,6 +35,8 @@ public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, $
@Override
public void add${entityName}(${entityName} ${entityName?uncap_first}) {
//新增时设置hasChild为0
${entityName?uncap_first}.set${hasChildrenField?cap_first}(I${entityName}Service.NOCHILD);
if(oConvertUtils.isEmpty(${entityName?uncap_first}.get${pidFieldName?cap_first}())){
${entityName?uncap_first}.set${pidFieldName?cap_first}(I${entityName}Service.ROOT_PID_VALUE);
}else{

View File

@ -59,7 +59,7 @@
<#elseif po.classType=='pca'>
<#if query_field_no gt 1> </#if><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
<#elseif po.classType=='popup'>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')"/>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
@ -265,7 +265,7 @@
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',

View File

@ -52,6 +52,7 @@
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"
<#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_depart'>

View File

@ -39,6 +39,8 @@ public class ${entityName} implements Serializable {
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'>
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode=', dicCode = "${po.dictField}"'>
<#elseif po.classType=='sel_tree'>
<#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText?split(",")[2]}", dicCode = "${po.dictText?split(",")[0]}"'>
</#if>
</#if>
/**${po.filedComment}*/

View File

@ -42,7 +42,7 @@
<#elseif po.classType=='pca'>
<#if query_field_no gt 1> </#if><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
<#elseif po.classType=='popup'>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')"/>
<#if query_field_no gt 1> </#if><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
@ -263,7 +263,7 @@
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType=='sel_search' || po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart'>
<#elseif po.classType=='sel_tree' || po.classType=='sel_search' || po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart'>
dataIndex: '${po.fieldName}_dictText',
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',

View File

@ -40,6 +40,7 @@
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"
<#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_depart'>

View File

@ -42,6 +42,7 @@
org-fields="${po.dictField}"
dest-fields="${Format.underlineToHump(po.dictText)}"
code="${po.dictTable}"
:multi="${po.extendParams.popupMulti?c}"
@input="popupCallback"
<#if po.readonly=='Y'>disabled</#if>/>
<#elseif po.classType =='sel_depart'>

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