Browse Source

公司间流程共享功能调整

user5 2 năm trước cách đây
mục cha
commit
7603b09a5d
20 tập tin đã thay đổi với 1230 bổ sung20 xóa
  1. 9 0
      jeeplus-api/jeeplus-system-api/src/main/java/com/jeeplus/sys/factory/UserApiFallbackFactory.java
  2. 18 0
      jeeplus-api/jeeplus-system-api/src/main/java/com/jeeplus/sys/feign/IUserApi.java
  3. 1 1
      jeeplus-common/jeeplus-common-mybatis-plus/src/main/java/com/jeeplus/config/TenantLineHandlerImpl.java
  4. 9 0
      jeeplus-modules/jeeplus-finance/src/main/java/com/jeeplus/finance/invoice/mapper/CwFinanceInvoiceMapper.java
  5. 97 0
      jeeplus-modules/jeeplus-finance/src/main/java/com/jeeplus/finance/invoice/mapper/xml/CwFinanceInvoiceMapper.xml
  6. 11 2
      jeeplus-modules/jeeplus-finance/src/main/java/com/jeeplus/finance/invoice/service/CwFinanceInvoiceService.java
  7. 99 1
      jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/common/handler/ExtUserTaskActivityBehavior.java
  8. 7 0
      jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/mapper/FlowMapper.java
  9. 9 0
      jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/mapper/xml/FlowMapper.xml
  10. 3 1
      jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/service/FlowProcessService.java
  11. 2 2
      jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/service/FlowTaskService.java
  12. 851 0
      jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/utils/StringUtils.java
  13. 2 1
      jeeplus-modules/jeeplus-public-modules/src/main/java/com/jeeplus/pubmodules/reimApprovalType/mapper/CwReimbursementTypeMapper.java
  14. 2 0
      jeeplus-modules/jeeplus-public-modules/src/main/java/com/jeeplus/pubmodules/serialNumTpl/mapper/SerialnumTplMapper.java
  15. 21 1
      jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/controller/UserController.java
  16. 10 0
      jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/feign/UserApiImpl.java
  17. 19 1
      jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/mapper/UserMapper.java
  18. 36 10
      jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/mapper/xml/UserMapper.xml
  19. 22 0
      jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/service/UserService.java
  20. 2 0
      jeeplus-modules/jeeplus-system/src/main/resources/bootstrap.yml

+ 9 - 0
jeeplus-api/jeeplus-system-api/src/main/java/com/jeeplus/sys/factory/UserApiFallbackFactory.java

@@ -56,6 +56,10 @@ public class UserApiFallbackFactory implements FallbackFactory <IUserApi> {
             public UserDTO getById(String id) {
                 return null;
             }
+            @Override
+            public UserDTO getFlowAbleById(String id) {
+                return null;
+            }
 
             @Override
             public List <UserDTO> findListByPostId(String postId) {
@@ -63,6 +67,11 @@ public class UserApiFallbackFactory implements FallbackFactory <IUserApi> {
             }
 
             @Override
+            public List <UserDTO> findListFlowAbleByPostId(String postId) {
+                return Lists.newArrayList ( );
+            }
+
+            @Override
             public List <UserDTO> findListByRoleId(String roleId) {
                 return Lists.newArrayList ( );
             }

+ 18 - 0
jeeplus-api/jeeplus-system-api/src/main/java/com/jeeplus/sys/feign/IUserApi.java

@@ -76,6 +76,15 @@ public interface IUserApi {
     UserDTO getById(@RequestParam("id") String id);
 
     /**
+     * 根据id获取用户
+     *
+     * @param id
+     * @return
+     */
+    @GetMapping(value = BASE_URL + "/getFlowAbleById")
+    UserDTO getFlowAbleById(@RequestParam("id") String id);
+
+    /**
      * 根据岗位id获取用户列表
      *
      * @param postId
@@ -85,6 +94,15 @@ public interface IUserApi {
     List <UserDTO> findListByPostId(@RequestParam("postId") String postId);
 
     /**
+     * 根据岗位id获取用户列表
+     *
+     * @param postId
+     * @return
+     */
+    @GetMapping(value = BASE_URL + "/findListFlowAbleByPostId")
+    List <UserDTO> findListFlowAbleByPostId(@RequestParam("postId") String postId);
+
+    /**
      * 根据角色id获取用户列表
      *
      * @param roleId

+ 1 - 1
jeeplus-common/jeeplus-common-mybatis-plus/src/main/java/com/jeeplus/config/TenantLineHandlerImpl.java

@@ -39,7 +39,7 @@ public class TenantLineHandlerImpl implements TenantLineHandler {
                 return true;
         }
         // flowable工作流系统表(排除扩展表)采用自身saas方案实现租户模式,在这里做忽略处理
-        if ( tableName.startsWith ( "act_" ) && !tableName.startsWith ( "act_extension" ) ) {
+        if ( (tableName.startsWith ( "act_" ) || tableName.startsWith ( "ACT_" )) ) {
             return true;
         }
 

+ 9 - 0
jeeplus-modules/jeeplus-finance/src/main/java/com/jeeplus/finance/invoice/mapper/CwFinanceInvoiceMapper.java

@@ -1,5 +1,6 @@
 package com.jeeplus.finance.invoice.mapper;
 
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
@@ -17,6 +18,7 @@ public interface CwFinanceInvoiceMapper extends BaseMapper<CwFinanceInvoice> {
 
     public IPage<CwFinanceInvoiceDTO> findList(Page<CwFinanceInvoiceDTO> page, @Param(Constants.WRAPPER) QueryWrapper<CwFinanceInvoice> queryWrapper, @Param("officeIds") String officeIds);
 
+    @InterceptorIgnore(tenantLine = "true")
     public CwFinanceInvoiceDTO queryById(@Param("id") String id);
 
     public List<String> getIdByProjectId(@Param("id") String id);
@@ -32,6 +34,13 @@ public interface CwFinanceInvoiceMapper extends BaseMapper<CwFinanceInvoice> {
      * @param id
      */
     void setReceivablesDateNull(@Param("id") String id);
+
+    /**
+     * 根据发票id清空发票的收款日期
+     * @param cwFinanceInvoice
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    void updateInfoById(CwFinanceInvoice cwFinanceInvoice);
 }
 
 

+ 97 - 0
jeeplus-modules/jeeplus-finance/src/main/java/com/jeeplus/finance/invoice/mapper/xml/CwFinanceInvoiceMapper.xml

@@ -304,4 +304,101 @@
     <update id="setReceivablesDateNull" parameterType="string">
         update cw_finance_invoice set receivables_date = null where id = #{id}
     </update>
+
+    <update id="updateInfoById">
+        update cw_finance_invoice set
+        <if test="null != delFlag and delFlag != ''">
+            del_flag = #{delFlag},
+        </if>
+        <if test="null != type and type != ''">
+            type = #{type},
+        </if>
+        <if test="null != billingType and billingType != ''">
+            billing_type = #{billingType},
+        </if>
+        <if test="null != billingWorkplaceReal and billingWorkplaceReal != ''">
+            billing_workplace_real = #{billingWorkplaceReal},
+        </if>
+        <if test="null != taxpayerIdentificationNo and taxpayerIdentificationNo != ''">
+            taxpayer_identification_no = #{taxpayerIdentificationNo},
+        </if>
+        <if test="null != address and address != ''">
+            address = #{address},
+        </if>
+        <if test="null != telPhone and telPhone != ''">
+            tel_phone = #{telPhone},
+        </if>
+        <if test="null != openBank and openBank != ''">
+            open_bank = #{openBank},
+        </if>
+        <if test="null != bankAccount and bankAccount != ''">
+            bank_account = #{bankAccount},
+        </if>
+        <if test="null != name and name != ''">
+            name = #{name},
+        </if>
+        <if test="null != receivablesType and receivablesType != ''">
+            receivables_type = #{receivablesType},
+        </if>
+        <if test="null != billingContent and billingContent != ''">
+            billing_content = #{billingContent},
+        </if>
+        <if test="null != account and account != ''">
+            account = #{account},
+        </if>
+        <if test="null != billingContentTerms and billingContentTerms != ''">
+            billing_content_terms = #{billingContentTerms},
+        </if>
+        <if test="null != billingPeople and billingPeople != ''">
+            billing_people = #{billingPeople},
+        </if>
+        <if test="null != billingDate">
+            billing_date = #{billingDate},
+        </if>
+        <if test="null != collectDate">
+            collect_date = #{collectDate},
+        </if>
+        <if test="null != billingPeopleReal and billingPeopleReal != ''">
+            billing_people_real = #{billingPeopleReal},
+        </if>
+        <if test="null != reconciliationPeople and reconciliationPeople != ''">
+            reconciliation_people = #{reconciliationPeople},
+        </if>
+        <if test="null != reconciliationArea and reconciliationArea != ''">
+            reconciliation_area = #{reconciliationArea},
+        </if>
+        <if test="null != billingWorkplaceRealId and billingWorkplaceRealId != ''">
+            billing_workplace_real_id = #{billingWorkplaceRealId},
+        </if>
+        <if test="null != billingPeopleId and billingPeopleId != ''">
+            billing_people_id = #{billingPeopleId},
+        </if>
+        <if test="null != status and status != ''">
+            status = #{status},
+        </if>
+        <if test="null != procInsId and procInsId != ''">
+            proc_ins_id = #{procInsId},
+        </if>
+        <if test="null != processDefinitionId and processDefinitionId != ''">
+            process_definition_id = #{processDefinitionId},
+        </if>
+        <if test="null != receivablesStatus and receivablesStatus != ''">
+            receivables_status = #{receivablesStatus},
+        </if>
+        <if test="null != invalidStatus and invalidStatus != ''">
+            invalid_status = #{invalidStatus},
+        </if>
+        <if test="null != receivablesDate">
+            receivables_date = #{receivablesDate},
+        </if>
+        <if test="null != isMultiple and isMultiple != ''">
+            is_multiple = #{isMultiple},
+        </if>
+        <if test="null != billingId and billingId != ''">
+            billing_id = #{billingId},
+        </if>
+
+        remarks = #{remarks}
+        where id = #{id}
+    </update>
 </mapper>

+ 11 - 2
jeeplus-modules/jeeplus-finance/src/main/java/com/jeeplus/finance/invoice/service/CwFinanceInvoiceService.java

@@ -327,7 +327,12 @@ public class CwFinanceInvoiceService extends ServiceImpl<CwFinanceInvoiceMapper,
                 }
             }
         }
-        this.saveOrUpdate(cwFinanceInvoice);
+        if(StringUtils.isNotBlank(cwFinanceInvoiceDTO.getId())){
+            cwFinanceInvoiceMapper.updateInfoById(cwFinanceInvoice);
+        }else{
+            cwFinanceInvoiceMapper.insert(cwFinanceInvoice);
+        }
+        //this.saveOrUpdate(cwFinanceInvoice);
 
         if (ObjectUtil.isNotEmpty(cwFinanceInvoiceDTO)) {
             // 如果当前是执行的是收款页面的保存方法
@@ -480,7 +485,11 @@ public class CwFinanceInvoiceService extends ServiceImpl<CwFinanceInvoiceMapper,
 
     public String updateStatusById(CwFinanceInvoiceDTO cwFinanceInvoiceDTO) {
         CwFinanceInvoice cwFinanceInvoice = CwFinanceInvoiceWrapper.INSTANCE.toEntity(cwFinanceInvoiceDTO);
-        cwFinanceInvoiceMapper.update(cwFinanceInvoice, new QueryWrapper<CwFinanceInvoice>().lambda().eq(CwFinanceInvoice::getId, cwFinanceInvoice.getId()));
+        if ("4".equals(cwFinanceInvoice.getStatus())) {
+            cwFinanceInvoiceMapper.updateInfoById(cwFinanceInvoice);
+        }else{
+            cwFinanceInvoiceMapper.update(cwFinanceInvoice, new QueryWrapper<CwFinanceInvoice>().lambda().eq(CwFinanceInvoice::getId, cwFinanceInvoice.getId()));
+        }
         return "操作成功";
     }
 

+ 99 - 1
jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/common/handler/ExtUserTaskActivityBehavior.java

@@ -8,8 +8,10 @@ import com.jeeplus.extension.domain.TaskDefExtension;
 import com.jeeplus.extension.service.TaskDefExtensionService;
 import com.jeeplus.extension.service.dto.FlowAssigneeDTO;
 import com.jeeplus.flowable.utils.FlowableUtils;
+import com.jeeplus.flowable.utils.StringUtils;
 import com.jeeplus.sys.feign.IUserApi;
 import com.jeeplus.sys.service.dto.UserDTO;
+import com.jeeplus.sys.utils.UserUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.flowable.bpmn.model.FlowElement;
 import org.flowable.bpmn.model.Process;
@@ -17,9 +19,11 @@ import org.flowable.bpmn.model.UserTask;
 import org.flowable.common.engine.impl.el.ExpressionManager;
 import org.flowable.engine.HistoryService;
 import org.flowable.engine.RepositoryService;
+import org.flowable.engine.RuntimeService;
 import org.flowable.engine.delegate.DelegateExecution;
 import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
 import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
+import org.flowable.engine.runtime.ProcessInstance;
 import org.flowable.task.api.history.HistoricTaskInstance;
 import org.flowable.task.service.TaskService;
 import org.flowable.task.service.impl.persistence.entity.TaskEntity;
@@ -67,7 +71,7 @@ public class ExtUserTaskActivityBehavior extends UserTaskActivityBehavior {
                     case "post":
                         if ( StrUtil.isNotBlank ( flowAssignee.getValue ( ) ) ) {
                             String postId = flowAssignee.getValue ( );
-                            List <UserDTO> userList = userApi.findListByPostId ( postId );
+                            List <UserDTO> userList = userApi.findListFlowAbleByPostId ( postId );
                             candidateUserIds.addAll ( CollectionUtils.extractToList ( userList, "id" ) );
                         }
 
@@ -115,6 +119,100 @@ public class ExtUserTaskActivityBehavior extends UserTaskActivityBehavior {
                         break;
                     case "custom":
                         //根据你的自定义标记,请自行实现
+                        //如果字符串中包含 "currentUserSql:" 则进行如下代码替换和处理
+                        if(flowAssignee.getValue ().contains("currentUserSql:")){
+                            //对应sql为:select su.* from sys_user_role a left join sys_role sr on sr.id = a.role_id left join sys_user su on su.id = a.user_id left join sys_office so on so.id = su.office_id where sr.en_name= 'bmzr' and so.id = (select office_id from sys_user where id = @currentUser.id)
+                            //用于查询当前登录人的部门主任人员信息
+                            UserDTO currentUserDTO = UserUtils.getCurrentUserDTO();
+                            String sql = flowAssignee.getValue ();
+                            if(sql.contains("@currentUser.id")){
+                                //将标志进行去除
+                                sql = sql.replaceAll("currentUserSql:","");
+                                //将判断条件进行替换
+                                sql = sql.replaceAll("@currentUser.id","'" + currentUserDTO.getId() + "'");
+                            }
+                            List<Map<String, Object>> maps = SpringUtil.getBean(JdbcTemplate.class).queryForList(sql);
+                            for (Map<String, Object> map : maps) {
+                                candidateUserIds.add(map.get ("id").toString ());
+                            }
+                        }
+                        //如果字符串中包含 "cwCurrentUserSql:" 则进行如下代码替换和处理
+                        if(flowAssignee.getValue ().contains("cwCurrentUserSql:")){
+                            //对应sql为:select su.* from sys_user_role a left join sys_role sr on sr.id = a.role_id left join sys_user su on su.id = a.user_id left join sys_office so on so.id = su.office_id where sr.en_name= 'bmzr' and so.id = (select office_id from sys_user where id = @currentUser.id)
+                            //用于查询当前登录人的部门主任人员信息
+                            UserDTO currentUserDTO = UserUtils.getCurrentUserDTO();
+                            String sql = flowAssignee.getValue ();
+                            if(sql.contains("@currentUser.id")){
+                                //将标志进行去除
+                                sql = sql.replaceAll("cwCurrentUserSql:","");
+                                //将判断条件进行替换
+                                sql = sql.replaceAll("@currentUser.id","'" + currentUserDTO.getId() + "'");
+                            }
+                            if(sql.contains("@currentUser.officeDTO.name")){
+                                //将标志进行去除
+                                sql = sql.replaceAll("cwCurrentUserSql:","");
+                                //将判断条件进行替换
+                                sql = sql.replaceAll("@currentUser.officeDTO.name","'" + currentUserDTO.getOfficeDTO().getName() + "'");
+                            }
+                            List<Map<String, Object>> maps = SpringUtil.getBean(JdbcTemplate.class).queryForList(sql);
+                            for (Map<String, Object> map : maps) {
+                                candidateUserIds.add(map.get ("id").toString ());
+                            }
+                        }
+                        if(flowAssignee.getValue ().contains("zsbxCurrentUserSql:")){
+                            //对应sql为:select su.* from sys_user_role a left join sys_role sr on sr.id = a.role_id left join sys_user su on su.id = a.user_id left join sys_office so on so.id = su.office_id where sr.en_name= 'bmzr' and so.id = (select office_id from sys_user where id = @currentUser.id)
+                            //用于查询当前登录人的部门主任人员信息
+                            UserDTO currentUserDTO = UserUtils.getCurrentUserDTO();
+                            String sql = flowAssignee.getValue ();
+                            if(sql.contains("@currentUser.id")){
+                                //将标志进行去除
+                                sql = sql.replaceAll("zsbxCurrentUserSql:","");
+                                //将判断条件进行替换
+                                sql = sql.replaceAll("@currentUser.id","'" + currentUserDTO.getId() + "'");
+                            }
+                            if(sql.contains("@currentUser.officeDTO.name")){
+                                //将标志进行去除
+                                sql = sql.replaceAll("zsbxCurrentUserSql:","");
+                                //将判断条件进行替换
+                                sql = sql.replaceAll("@currentUser.officeDTO.name","'" + currentUserDTO.getOfficeDTO().getName() + "'");
+                            }
+                            List<Map<String, Object>> maps = SpringUtil.getBean(JdbcTemplate.class).queryForList(sql);
+                            for (Map<String, Object> map : maps) {
+                                candidateUserIds.add(map.get ("id").toString ());
+                            }
+                        }
+                        //如果字符串中包含 "gsldbxCurrentUserSql:" 则进行如下代码替换和处理
+                        if(flowAssignee.getValue ().contains("gsldbxCurrentUserSql:")){
+                            String sql = flowAssignee.getValue ();
+                            // 流程发起人
+                            ProcessInstance processInstance = SpringUtil.getBean(RuntimeService.class)
+                                    .createProcessInstanceQuery()
+                                    .processInstanceId(execution.getProcessInstanceId())
+                                    .singleResult();
+                            if(null != processInstance && StringUtils.isNotBlank(processInstance.getStartUserId())){
+                                String startUserId = processInstance.getStartUserId();
+                                //通过查询流程发起人确认发起人所在部门以及部门分管领导信息
+                                if(sql.contains("@currentUser.id")){
+                                    //将标志进行去除
+                                    sql = sql.replaceAll("gsldbxCurrentUserSql:","");
+                                    //将判断条件进行替换
+                                    sql = sql.replaceAll("@currentUser.id","'" + startUserId + "'");
+                                }
+                            } else {
+                                //如果找不到发起人信息 则审核人默认为 角色 总经办人员信息
+                                sql = "SELECT su.* FROM sys_user_role a LEFT JOIN sys_role sr ON sr.id = a.role_id LEFT JOIN sys_user su ON su.id = a.user_id LEFT JOIN sys_office so ON so.id = su.office_id WHERE sr.en_name = 'zjb'";
+                            }
+                            //设定部门分管领导为审核人
+                            List<Map<String, Object>> maps = SpringUtil.getBean(JdbcTemplate.class).queryForList(sql);
+                            if(null == maps || maps.size()==0){
+                                sql = "SELECT su.* FROM sys_user_role a LEFT JOIN sys_role sr ON sr.id = a.role_id LEFT JOIN sys_user su ON su.id = a.user_id LEFT JOIN sys_office so ON so.id = su.office_id WHERE sr.en_name = 'zjb'";
+                                maps = SpringUtil.getBean(JdbcTemplate.class).queryForList(sql);
+                            }
+                            for (Map<String, Object> map : maps) {
+                                candidateUserIds.add(map.get ("id").toString ());
+                            }
+                        }
+
                         break;
                 }
             }

+ 7 - 0
jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/mapper/FlowMapper.java

@@ -26,4 +26,11 @@ public interface FlowMapper extends BaseMapper <Flow> {
      */
     ActRuTaskInfo getTaskInfoByTaskId(String taskId);
 
+    /**
+     * 查询流程对应租户id
+     * @param procDefKey
+     * @return
+     */
+    String getTenantIdByProcDefKey(String procDefKey);
+
 }

+ 9 - 0
jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/mapper/xml/FlowMapper.xml

@@ -52,4 +52,13 @@
 		limit 1
 	</select>
 
+    <select id="getTenantIdByProcDefKey" resultType="java.lang.String">
+		select
+		  TENANT_ID_ as "tenantId"
+		from
+		  ACT_RE_PROCDEF
+		where KEY_ = #{procDefKey}
+		limit 1
+	</select>
+
 </mapper>

+ 3 - 1
jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/service/FlowProcessService.java

@@ -4,6 +4,7 @@
 package com.jeeplus.flowable.service;
 
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -132,8 +133,9 @@ public class FlowProcessService {
     /**
      * 流程定义列表
      */
+    @InterceptorIgnore(tenantLine = "true")
     public Page <Map> processList(Page <Map> page, String category) {
-        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery ( ).processDefinitionTenantId ( tenantApi.getCurrentTenantId ( ) ).active ( )
+        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery ( )/*.processDefinitionTenantId ( tenantApi.getCurrentTenantId ( ) )*/.active ( )
                 .latestVersion ( ).orderByProcessDefinitionKey ( ).asc ( );
         if ( StrUtil.isNotEmpty ( category ) ) {
             processDefinitionQuery.processDefinitionCategory ( category );

+ 2 - 2
jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/service/FlowTaskService.java

@@ -411,7 +411,7 @@ public class FlowTaskService {
         }
 
         // 启动流程
-        ProcessInstance procIns = runtimeService.startProcessInstanceByKeyAndTenantId ( procDefKey, businessTable + ":" + businessId, vars, tenantApi.getCurrentTenantId ( ) );
+        ProcessInstance procIns = runtimeService.startProcessInstanceByKeyAndTenantId ( procDefKey, businessTable + ":" + businessId, vars, /*tenantApi.getCurrentTenantId ( )*/ flowMapper.getTenantIdByProcDefKey(procDefKey) );
 
         // 更新业务表流程实例ID
         Flow act = new Flow ( );
@@ -547,7 +547,7 @@ public class FlowTaskService {
         }
         // 获取任务执行人名称
         if ( StrUtil.isNotEmpty ( histIns.getAssignee ( ) ) ) {
-            UserDTO user = userApi.getById ( histIns.getAssignee ( ) );
+            UserDTO user = userApi.getFlowAbleById ( histIns.getAssignee ( ) );
             if ( user != null ) {
                 e.setAssignee ( histIns.getAssignee ( ) );
                 e.setAssigneeName ( user.getName ( ) );

+ 851 - 0
jeeplus-modules/jeeplus-flowable/src/main/java/com/jeeplus/flowable/utils/StringUtils.java

@@ -0,0 +1,851 @@
+/**
+ * Copyright &copy; 2013-2017 <a href="http://www.rhcncpa.com/">瑞华会计师事务所</a> All rights reserved.
+ */
+package com.jeeplus.flowable.utils;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.sys.utils.SpringContextHolder;
+import com.jeeplus.utils.Encodes;
+import net.sf.json.JSONObject;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.servlet.LocaleResolver;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
+ * @author jeeplus
+ * @version 2013-05-22
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils {
+
+	private static final char SEPARATOR = '_';
+	private static final String CHARSET_NAME = "UTF-8";
+	private static final int DEF_DIV_SCALE = 10; //这个类不能实例化
+	public static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+	public static SimpleDateFormat sdfs = new SimpleDateFormat("HHmm");
+
+	/**
+	 * 转换为字节数组
+	 * @param str
+	 * @return
+	 */
+	public static byte[] getBytes(String str){
+		if (str != null){
+			try {
+				return str.getBytes(CHARSET_NAME);
+			} catch (UnsupportedEncodingException e) {
+				return null;
+			}
+		}else{
+			return null;
+		}
+	}
+
+	/**
+	 * 转换为字节数组
+	 * @param bytes
+	 * @return
+	 */
+	public static String toString(byte[] bytes){
+		try {
+			return new String(bytes, CHARSET_NAME);
+		} catch (UnsupportedEncodingException e) {
+			return EMPTY;
+		}
+	}
+
+	/**
+	 * 是否包含字符串
+	 * @param str 验证字符串
+	 * @param strs 字符串组
+	 * @return 包含返回true
+	 */
+	public static boolean inString(String str, String... strs){
+		if (str != null){
+			for (String s : strs){
+				if (str.equals(trim(s))){
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * 替换掉HTML标签方法
+	 */
+	public static String replaceHtml(String html) {
+		if (isBlank(html)){
+			return "";
+		}
+		String regEx = "<.+?>";
+		Pattern p = Pattern.compile(regEx);
+		Matcher m = p.matcher(html);
+		String s = m.replaceAll("");
+		return s;
+	}
+
+	/**
+	 * 替换为手机识别的HTML,去掉样式及属性,保留回车。
+	 * @param html
+	 * @return
+	 */
+	public static String replaceMobileHtml(String html){
+		if (html == null){
+			return "";
+		}
+		return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
+	}
+
+	/**
+	 * 替换为手机识别的HTML,去掉样式及属性,保留回车。
+	 * @param txt
+	 * @return
+	 */
+	public static String toHtml(String txt){
+		if (txt == null){
+			return "";
+		}
+		return replace(replace(Encodes.escapeHtml(txt), "\n", "<br/>"), "\t", "&nbsp; &nbsp; ");
+	}
+
+	/**
+	 * 缩略字符串(不区分中英文字符)
+	 * @param str 目标字符串
+	 * @param length 截取长度
+	 * @return
+	 */
+	public static String abbr(String str, int length) {
+		if (str == null) {
+			return "";
+		}
+		try {
+			StringBuilder sb = new StringBuilder();
+			int currentLength = 0;
+			for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
+				currentLength += String.valueOf(c).getBytes("GBK").length;
+				if (currentLength <= length - 3) {
+					sb.append(c);
+				} else {
+					sb.append("...");
+					break;
+				}
+			}
+			return sb.toString();
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return "";
+	}
+
+	public static String abbr2(String param, int length) {
+		if (param == null) {
+			return "";
+		}
+		StringBuffer result = new StringBuffer();
+		int n = 0;
+		char temp;
+		boolean isCode = false; // 是不是HTML代码
+		boolean isHTML = false; // 是不是HTML特殊字符,如&nbsp;
+		for (int i = 0; i < param.length(); i++) {
+			temp = param.charAt(i);
+			if (temp == '<') {
+				isCode = true;
+			} else if (temp == '&') {
+				isHTML = true;
+			} else if (temp == '>' && isCode) {
+				n = n - 1;
+				isCode = false;
+			} else if (temp == ';' && isHTML) {
+				isHTML = false;
+			}
+			try {
+				if (!isCode && !isHTML) {
+					n += String.valueOf(temp).getBytes("GBK").length;
+				}
+			} catch (UnsupportedEncodingException e) {
+				e.printStackTrace();
+			}
+
+			if (n <= length - 3) {
+				result.append(temp);
+			} else {
+				result.append("...");
+				break;
+			}
+		}
+		// 取出截取字符串中的HTML标记
+		String temp_result = result.toString().replaceAll("(>)[^<>]*(<?)",
+				"$1$2");
+		// 去掉不需要结素标记的HTML标记
+		temp_result = temp_result
+				.replaceAll(
+						"</?(AREA|BASE|BASEFONT|BODY|BR|COL|COLGROUP|DD|DT|FRAME|HEAD|HR|HTML|IMG|INPUT|ISINDEX|LI|LINK|META|OPTION|P|PARAM|TBODY|TD|TFOOT|TH|THEAD|TR|area|base|basefont|body|br|col|colgroup|dd|dt|frame|head|hr|html|img|input|isindex|li|link|meta|option|p|param|tbody|td|tfoot|th|thead|tr)[^<>]*/?>",
+						"");
+		// 去掉成对的HTML标记
+		temp_result = temp_result.replaceAll("<([a-zA-Z]+)[^<>]*>(.*?)</\\1>",
+				"$2");
+		// 用正则表达式取出标记
+		Pattern p = Pattern.compile("<([a-zA-Z]+)[^<>]*>");
+		Matcher m = p.matcher(temp_result);
+		List<String> endHTML = Lists.newArrayList();
+		while (m.find()) {
+			endHTML.add(m.group(1));
+		}
+		// 补全不成对的HTML标记
+		for (int i = endHTML.size() - 1; i >= 0; i--) {
+			result.append("</");
+			result.append(endHTML.get(i));
+			result.append(">");
+		}
+		return result.toString();
+	}
+
+	/**
+	 * 转换为Double类型
+	 */
+	public static Double toDouble(Object val){
+		if (val == null){
+			return 0D;
+		}
+		try {
+			return Double.valueOf(trim(val.toString()));
+		} catch (Exception e) {
+			return 0D;
+		}
+	}
+
+	/**
+	 * 转换为Float类型
+	 */
+	public static Float toFloat(Object val){
+		return toDouble(val).floatValue();
+	}
+
+	/**
+	 * 转换为Long类型
+	 */
+	public static Long toLong(Object val){
+		return toDouble(val).longValue();
+	}
+
+	/**
+	 * 转换为Integer类型
+	 */
+	public static Integer toInteger(Object val){
+		return toLong(val).intValue();
+	}
+
+	/**
+	 * 获得i18n字符串
+	 */
+	public static String getMessage(String code, Object[] args) {
+		LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class);
+		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+		Locale localLocale = localLocaleResolver.resolveLocale(request);
+		return SpringContextHolder.getApplicationContext().getMessage(code, args, localLocale);
+	}
+
+	/**
+	 * 获得用户远程地址
+	 */
+	public static String getRemoteAddr(HttpServletRequest request){
+		String remoteAddr = request.getHeader("X-Real-IP");
+		if (isNotBlank(remoteAddr)) {
+			remoteAddr = request.getHeader("X-Forwarded-For");
+		}else if (isNotBlank(remoteAddr)) {
+			remoteAddr = request.getHeader("Proxy-Client-IP");
+		}else if (isNotBlank(remoteAddr)) {
+			remoteAddr = request.getHeader("WL-Proxy-Client-IP");
+		}
+		return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
+	}
+
+	/**
+	 * 驼峰命名法工具
+	 * @return
+	 * 		toCamelCase("hello_world") == "helloWorld"
+	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
+	 * 		toUnderScoreCase("helloWorld") = "hello_world"
+	 */
+	public static String toCamelCase(String s) {
+		if (s == null) {
+			return null;
+		}
+
+		s = s.toLowerCase();
+
+		StringBuilder sb = new StringBuilder(s.length());
+		boolean upperCase = false;
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+
+			if (c == SEPARATOR) {
+				upperCase = true;
+			} else if (upperCase) {
+				sb.append(Character.toUpperCase(c));
+				upperCase = false;
+			} else {
+				sb.append(c);
+			}
+		}
+
+		return sb.toString();
+	}
+
+	/**
+	 * 驼峰命名法工具
+	 * @return
+	 * 		toCamelCase("hello_world") == "helloWorld"
+	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
+	 * 		toUnderScoreCase("helloWorld") = "hello_world"
+	 */
+	public static String toCapitalizeCamelCase(String s) {
+		if (s == null) {
+			return null;
+		}
+		s = toCamelCase(s);
+		return s.substring(0, 1).toUpperCase() + s.substring(1);
+	}
+
+	/**
+	 * 驼峰命名法工具
+	 * @return
+	 * 		toCamelCase("hello_world") == "helloWorld"
+	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
+	 * 		toUnderScoreCase("helloWorld") = "hello_world"
+	 */
+	public static String toUnderScoreCase(String s) {
+		if (s == null) {
+			return null;
+		}
+
+		StringBuilder sb = new StringBuilder();
+		boolean upperCase = false;
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+
+			boolean nextUpperCase = true;
+
+			if (i < (s.length() - 1)) {
+				nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
+			}
+
+			if ((i > 0) && Character.isUpperCase(c)) {
+				if (!upperCase || !nextUpperCase) {
+					sb.append(SEPARATOR);
+				}
+				upperCase = true;
+			} else {
+				upperCase = false;
+			}
+
+			sb.append(Character.toLowerCase(c));
+		}
+
+		return sb.toString();
+	}
+
+	/**
+	 * 如果不为空,则设置值
+	 * @param target
+	 * @param source
+	 */
+	public static void setValueIfNotBlank(String target, String source) {
+		if (isNotBlank(source)){
+			target = source;
+		}
+	}
+
+	/**
+	 * 转换为JS获取对象值,生成三目运算返回结果
+	 * @param objectString 对象串
+	 *   例如:row.user.id
+	 *   返回:!row?'':!row.user?'':!row.user.id?'':row.user.id
+	 */
+	public static String jsGetVal(String objectString){
+		StringBuilder result = new StringBuilder();
+		StringBuilder val = new StringBuilder();
+		String[] vals = split(objectString, ".");
+		for (int i=0; i<vals.length; i++){
+			val.append("." + vals[i]);
+			result.append("!"+(val.substring(1))+"?'':");
+		}
+		result.append(val.substring(1));
+		return result.toString();
+	}
+
+
+
+	public static boolean isChinese(char c) {
+		Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
+		if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
+				|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
+				|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
+				|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
+			return true;
+		}
+		return false;
+	}
+
+	public static Map<String, String> StringToJson(String contentStr){
+		HashMap<String, String> requestMap = new HashMap<String, String>();
+
+
+		JSONObject jsonObject = JSONObject.fromObject(contentStr);//
+		Iterator<String> keys = jsonObject.keys();// 定义迭代器
+		String key = null;
+		String value = null;
+		while (keys.hasNext()) {
+			key = keys.next().toString();
+			value = jsonObject.get(key).toString();
+			requestMap.put(key.trim(), value.trim());
+		}
+		return requestMap;
+	}
+
+	/**
+	 * 根据键值对填充字符串,如("hello {name}",{name:"xiaoming"})
+	 * 输出:
+	 * @param content
+	 * @param map
+	 * @return
+	 */
+	public static String renderString(String content, Map<String, String> map){
+		Set<Map.Entry<String, String>> sets = map.entrySet();
+		for(Map.Entry<String, String> entry : sets) {
+			String regex = "\\{" + entry.getKey() + "\\}";
+			Pattern pattern = Pattern.compile(regex);
+			Matcher matcher = pattern.matcher(content);
+			content = matcher.replaceAll(entry.getValue());
+		}
+		return content;
+	}
+
+	/**
+	 * 提供精确的加法运算。
+	 * @param v1 被加数
+	 * @param v2 加数
+	 * @return 两个参数的和
+	 */
+	public static double add(double v1,double v2){
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.add(b2).doubleValue();
+	}
+	/**
+	 * 提供精确的减法运算。
+	 * @param v1 被减数
+	 * @param v2 减数
+	 * @return 两个参数的差
+	 */
+	public static double sub(double v1,double v2){
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.subtract(b2).doubleValue();
+	}
+	/**
+	 * 提供精确的乘法运算。
+	 * @param v1 被乘数
+	 * @param v2 乘数
+	 * @return 两个参数的积
+	 */
+	public static double mul(double v1,double v2){
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.multiply(b2).doubleValue();
+	}
+	/**
+	 * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
+	 * 小数点以后10位,以后的数字四舍五入。
+	 * @param v1 被除数
+	 * @param v2 除数
+	 * @return 两个参数的商
+	 */
+	public static double div(double v1,double v2){
+		return div(v1,v2,DEF_DIV_SCALE);
+	}
+	/**
+	 * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
+	 * 定精度,以后的数字四舍五入。
+	 * @param v1 被除数
+	 * @param v2 除数
+	 * @param scale 表示表示需要精确到小数点以后几位。
+	 * @return 两个参数的商
+	 */
+	public static double div(double v1,double v2,int scale){
+		if(scale<0){
+			throw new IllegalArgumentException(
+					"The scale must be a positive integer or zero");
+		}
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
+	}
+	/**
+	 * 提供精确的小数位四舍五入处理。
+	 * @param v 需要四舍五入的数字
+	 * @param scale 小数点后保留几位
+	 * @return 四舍五入后的结果
+	 */
+	public static double round(double v,int scale){
+		if(scale<0){
+			throw new IllegalArgumentException("The scale must be a positive integer or zero");
+		}
+		BigDecimal b = new BigDecimal(Double.toString(v));
+		BigDecimal one = new BigDecimal("1");
+		return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
+	}
+
+	public static Map<String,String> getByDictMap(){
+		Map<String,String> map = new HashMap<>();
+		map.put("13","报销申请");
+		map.put("16","合同申请");
+		map.put("21","发票申请");
+		map.put("38","案例登记");
+		map.put("39","项目登记");
+		map.put("40","退票申请");
+		map.put("41","项目变更");
+		map.put("42","合同归档");
+		map.put("43","合同作废");
+		map.put("44","合同变更");
+		map.put("45","报告申请");
+		map.put("46","报告变更");
+		map.put("47","报告作废");
+		map.put("48","发票变更");
+		map.put("49","退票变更");
+		map.put("50","投标申请");
+		map.put("51","报告归档");
+		map.put("52","收入结算");
+		map.put("53","收入调整");
+		map.put("54","调整作废");
+		map.put("55","收文申请");
+		map.put("56","行政盖章");
+		map.put("57","采购合同");
+		map.put("58","日常事务");
+		map.put("59","借用申请");
+		map.put("60","归还借用");
+		map.put("61","采购申请");
+		map.put("62","发文申请");
+		map.put("63","报废申请");
+		map.put("64","领用申请");
+		map.put("66","转正申请");
+		map.put("67","劳动关系");
+		map.put("68","部门调转");
+		map.put("69","日常事务");
+		map.put("70","职级调整");
+		map.put("71","离职申请");
+		map.put("72","合同完成");
+		map.put("74","系统预警");
+		map.put("75","加入企业");
+		map.put("76","案例申请");
+		map.put("77","加班申请");
+		map.put("78","出差申请");
+		map.put("79","外勤申请");
+		map.put("80","请假申请");
+		map.put("81","销假申请");
+		map.put("82","续假申请");
+		map.put("83","补卡申请");
+		map.put("84","考勤审批");
+		return map;
+	}
+
+	public static String firstDay(String month,String day,String companyId) {
+		if(StringUtils.isBlank(month)) {
+			if (StringUtils.isBlank(day)) {
+				//获取上月第一天:
+				Calendar c = Calendar.getInstance();
+				c.add(Calendar.MONTH, -1);
+				c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
+				String first = format.format(c.getTime());
+				return first;
+			}else{
+				Calendar now = Calendar.getInstance();
+				int nowDay = now.get(Calendar.DAY_OF_MONTH);
+				now.set(Calendar.DAY_OF_MONTH, 0);
+				String last = format.format(now.getTime()).substring(8,10);
+				if (last.equals(day)){
+					return format.format(now.getTime()).substring(0,8)+"01";
+				}else {
+					if (nowDay < Integer.parseInt(day)) {
+						//获取上月第一天:
+						Calendar c = Calendar.getInstance();
+						c.add(Calendar.MONTH, -2);
+						c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
+						String first = format.format(c.getTime()).substring(0, 8) + (Integer.parseInt(day) < 10 ? "0" + Integer.parseInt(day) : day);
+						return first;
+					} else {
+						//获取上月第一天:
+						Calendar c = Calendar.getInstance();
+						c.add(Calendar.MONTH, -1);
+						c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
+						String first = format.format(c.getTime()).substring(0, 8) + (Integer.parseInt(day) < 10 ? "0" + Integer.parseInt(day) : day);
+						return first;
+					}
+				}
+			}
+		}else{
+			if (StringUtils.isBlank(day)) {
+				return month+"-01";
+			}else {
+				int m = Integer.parseInt(month.substring(5,7))-1;
+				if (m==1){
+					int year = Integer.parseInt(month.substring(0,4)) - 1;
+					return year+"-01-"+(Integer.parseInt(day)<10?"0"+day:day);
+				}else if(m>10){
+					return month.substring(0,5)+m+"-"+(Integer.parseInt(day)<10?"0"+Integer.parseInt(day):day);
+				}else{
+					return month.substring(0,5)+"0"+m+"-"+(Integer.parseInt(day)<10?"0"+Integer.parseInt(day):day);
+				}
+			}
+		}
+	}
+	public static String lastDay(String month,String day,String companyId) {
+		if(StringUtils.isBlank(month)) {
+			if (StringUtils.isBlank(day)) {
+				//获取上月最后一天
+				Calendar ca = Calendar.getInstance();
+				ca.set(Calendar.DAY_OF_MONTH, 0);
+				String last = format.format(ca.getTime());
+				return last;
+			}else{
+				Calendar now = Calendar.getInstance();
+				int nowDay = now.get(Calendar.DAY_OF_MONTH);
+				now.set(Calendar.DAY_OF_MONTH, 0);
+				String l = format.format(now.getTime()).substring(8,10);
+				if (l.equals(day)){
+					return format.format(now.getTime()).substring(0,8)+day;
+				}else {
+					if (nowDay < Integer.parseInt(day)) {
+						//获取上月最后一天
+
+						int days = Integer.parseInt(day) - 1;
+						if (days>0) {
+							Calendar ca = Calendar.getInstance();
+							ca.set(Calendar.DAY_OF_MONTH, 0);
+							String last = format.format(ca.getTime()).substring(0, 8) + (days < 10 ? "0" + days : days);
+							return last;
+						}else {
+							Calendar ca = Calendar.getInstance();
+							ca.set(Calendar.DAY_OF_MONTH, 1);
+							return format.format(ca.getTime());
+						}
+					} else {
+						//获取上月最后一天
+						int days = Integer.parseInt(day) - 1;
+						if (days>0) {
+							Calendar ca = Calendar.getInstance();
+							ca.set(Calendar.DAY_OF_MONTH, +1);
+							String last = format.format(ca.getTime()).substring(0, 8) + (days < 10 ? "0" + days : days);
+							return last;
+						}else {
+							Calendar ca = Calendar.getInstance();
+							ca.set(Calendar.DAY_OF_MONTH, 0);
+							return format.format(ca.getTime());
+						}
+					}
+				}
+			}
+		}else {
+			if (StringUtils.isBlank(day)) {
+				//格式化日期
+				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+				Calendar cal = Calendar.getInstance();
+				//设置年份
+				cal.set( Integer.parseInt(month.substring(0,4)),(Integer.parseInt(month.substring(5,7))-1),1);
+				//设置月份
+				//获取某月最大天数
+				int lastDay = cal.getActualMaximum(Calendar.DATE);
+				//设置日历中月份的最大天数
+				cal.set(Calendar.DAY_OF_MONTH, lastDay);
+				return sdf.format(cal.getTime());
+			}else {
+				int days = Integer.parseInt(day)-1;
+				if (days>0){
+					return month+"-"+(days<10?"0"+days:days);
+				}else{
+					Calendar calendar = Calendar.getInstance();
+					Date date = null;
+					try {
+						date = format.parse(month+"-01");
+					} catch (ParseException e) {
+						e.printStackTrace();
+					}
+					calendar.setTime(date);
+					calendar.set(Calendar.DAY_OF_MONTH, -1);
+					int lastDay = calendar.getActualMaximum(Calendar.DATE);
+					//设置日历中月份的最大天数
+					calendar.set(Calendar.DAY_OF_MONTH, lastDay);
+					return format.format(calendar.getTime());
+				}
+			}
+		}
+	}
+	public static Boolean isWeek(String day) {
+		SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");
+		Date date= null;//取时间
+		try {
+			date = sdfDay.parse(day);
+			Calendar calendar = Calendar.getInstance();
+			calendar.setTime(date);
+			int week  =  calendar.get(Calendar.DAY_OF_WEEK)-1;
+			if (week==0 || week==6){
+				return true;
+			}else {
+				return false;
+			}
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		return false;
+	}
+
+	public static int lateEarlyTime(String cardType,Date start,Date end,Date now){
+		Integer nowh = Integer.parseInt(sdfs.format(new Date()).substring(0,2));
+		Integer nowm = Integer.parseInt(sdfs.format(new Date()).substring(2,4));
+		if (cardType.equals("1")){
+			Integer ruleh = Integer.parseInt(sdfs.format(start).substring(0,2));
+			Integer rulem = Integer.parseInt(sdfs.format(start).substring(2,4));
+			if (ruleh - nowh < 0 && rulem >= nowm){
+				return nowh - ruleh;
+			}else if(ruleh - nowh < 0 && rulem < nowm){
+				return nowh - ruleh + 1;
+			}else {
+				return 0;
+			}
+		}else {
+			Integer ruleh = Integer.parseInt(sdfs.format(end).substring(0,2));
+			Integer rulem = Integer.parseInt(sdfs.format(end).substring(2,4));
+			if (ruleh - nowh > 0 && rulem > nowm){
+				return ruleh - nowh + 1;
+			}else if(ruleh - nowh > 0 && rulem <= nowm){
+				return ruleh - nowh;
+			}else {
+				return 0;
+			}
+		}
+	}
+
+	public static Map<String,String> getMonth() {
+		//获取上月最后一天
+		Calendar ca = Calendar.getInstance();
+		String month = format.format(ca.getTime()).substring(0,7);
+		ca.set(Calendar.DAY_OF_MONTH, 0);
+		String oldMonth = format.format(ca.getTime()).substring(0,7);
+		Map<String,String> map = new HashMap<>();
+		map.put("1",month);
+		map.put("2",oldMonth);
+		return map;
+	}
+
+
+	/**
+	 * date转Str
+	 * @param currentTime
+	 * @return
+	 */
+	public static String getDateStr(Date currentTime) {
+		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+		String dateString = formatter.format(currentTime);
+		return dateString;
+	}
+
+
+	//@ author: walker
+
+	/**
+	 * ⽤正则表达式判断字符串是否为数字(含负数)
+	 * @param str
+	 * @return
+	 */
+	public static boolean isNumeric(String str) {
+		String regEx = "^-?[0-9]+$";
+		Pattern pat = Pattern.compile(regEx);
+		Matcher mat = pat.matcher(str);
+		if (mat.find()) {
+			return true;
+		}else {
+			return false;
+		}
+	}
+
+
+	/**
+	 * 是否包含字符串
+	 *
+	 * @param str 验证字符串
+	 * @param strs 字符串组
+	 * @return 包含返回true
+	 */
+	public static boolean inStringIgnoreCase(String str, String... strs)
+	{
+		if (str != null && strs != null)
+		{
+			for (String s : strs)
+			{
+				if (str.equalsIgnoreCase(trim(s)))
+				{
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+	 *
+	 * @param name 转换前的下划线大写方式命名的字符串
+	 * @return 转换后的驼峰式命名的字符串
+	 */
+	public static String convertToCamelCase(String name)
+	{
+		StringBuilder result = new StringBuilder();
+		// 快速检查
+		if (name == null || name.isEmpty())
+		{
+			// 没必要转换
+			return "";
+		}
+		else if (!name.contains("_"))
+		{
+			// 不含下划线,仅将首字母大写
+			return name.substring(0, 1).toUpperCase() + name.substring(1);
+		}
+		// 用下划线将原始字符串分割
+		String[] camels = name.split("_");
+		for (String camel : camels)
+		{
+			// 跳过原始字符串中开头、结尾的下换线或双重下划线
+			if (camel.isEmpty())
+			{
+				continue;
+			}
+			// 首字母大写
+			result.append(camel.substring(0, 1).toUpperCase());
+			result.append(camel.substring(1).toLowerCase());
+		}
+		return result.toString();
+	}
+
+	/**
+	 * * 判断一个对象是否为空
+	 *
+	 * @param object Object
+	 * @return true:为空 false:非空
+	 */
+	public static boolean isNull(Object object)
+	{
+		return object == null;
+	}
+}

+ 2 - 1
jeeplus-modules/jeeplus-public-modules/src/main/java/com/jeeplus/pubmodules/reimApprovalType/mapper/CwReimbursementTypeMapper.java

@@ -1,5 +1,6 @@
 package com.jeeplus.pubmodules.reimApprovalType.mapper;
 
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -26,7 +27,7 @@ public interface CwReimbursementTypeMapper extends BaseMapper<CwReimbursementTyp
      */
     List<CwReimbursementTypeInfo> findList(@Param(Constants.WRAPPER) Wrapper<CwReimbursementTypeInfo> queryWrapper);
 
-
+    @InterceptorIgnore(tenantLine = "true")
     List<CwReimbursementTypeInfo> bxList2(@Param(Constants.WRAPPER) Wrapper<CwReimbursementTypeInfo> queryWrapper,
                                           @Param("officeId") String officeId);
 

+ 2 - 0
jeeplus-modules/jeeplus-public-modules/src/main/java/com/jeeplus/pubmodules/serialNumTpl/mapper/SerialnumTplMapper.java

@@ -1,5 +1,6 @@
 package com.jeeplus.pubmodules.serialNumTpl.mapper;
 
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -12,6 +13,7 @@ public interface SerialnumTplMapper extends BaseMapper<SysSerialnumTpl> {
 
     IPage<SysSerialnumTpl> pageList(Page<SysSerialnumTpl> page, @Param(Constants.WRAPPER) QueryWrapper queryWrapper);
 
+    @InterceptorIgnore(tenantLine = "true")
     SysSerialnumTpl queryByComAndBizCode(@Param("id")String id, @Param("bizCode")String bizCode);
 
     void resetSerialNum(@Param("id")String id,@Param("yearBuilt")String yearBuilt,@Param("newYear")String newYear);

+ 21 - 1
jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/controller/UserController.java

@@ -121,7 +121,7 @@ public class UserController {
      */
     @ApiLog("用户数据列表")
     @ApiOperation(value = "用户数据列表")
-    @PreAuthorize("hasAuthority('sys:user:list')")
+    //@PreAuthorize("hasAuthority('sys:user:list')")
     @GetMapping("list")
     public ResponseEntity list(UserDTO userDTO, Page <UserDTO> page) throws Exception {
         QueryWrapper <UserDTO> queryWrapper = QueryWrapperGenerator.buildQueryCondition ( userDTO, UserDTO.class );
@@ -132,6 +132,26 @@ public class UserController {
         return ResponseEntity.ok ( result );
     }
 
+    /**
+     * 查询列表(排除admin)
+     *
+     * @param userDTO
+     * @param page
+     * @return
+     */
+    @ApiLog("用户数据列表")
+    @ApiOperation(value = "用户数据列表")
+    @PreAuthorize("hasAuthority('sys:user:list')")
+    @GetMapping("list2")
+    public ResponseEntity list2(UserDTO userDTO, Page <UserDTO> page) throws Exception {
+        QueryWrapper <UserDTO> queryWrapper = QueryWrapperGenerator.buildQueryCondition ( userDTO, UserDTO.class );
+        if ( userDTO.getTenantDTO ( ) != null && StrUtil.isNotBlank ( userDTO.getTenantDTO ( ).getId ( ) ) ) {
+            queryWrapper.eq ( "a.tenant_id", userDTO.getTenantDTO ( ).getId ( ) );
+        }
+        IPage <UserDTO> result = userService.findPage2 ( page, queryWrapper );
+        return ResponseEntity.ok ( result );
+    }
+
 
     /**
      * 保存用户

+ 10 - 0
jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/feign/UserApiImpl.java

@@ -65,11 +65,21 @@ public class UserApiImpl implements IUserApi {
     }
 
     @Override
+    public UserDTO getFlowAbleById(String id) {
+        return userService.getFlowAbleById ( id );
+    }
+
+    @Override
     public List <UserDTO> findListByPostId(String postId) {
         return userService.findListByPostId ( postId );
     }
 
     @Override
+    public List<UserDTO> findListFlowAbleByPostId(String postId) {
+        return userService.findListFlowAbleByPostId ( postId );
+    }
+
+    @Override
     public List <UserDTO> findListByRoleId(String roleId) {
         return userService.findListByRoleId ( roleId );
     }

+ 19 - 1
jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/mapper/UserMapper.java

@@ -47,9 +47,18 @@ public interface UserMapper extends BaseMapper <User> {
      * @param queryWrapper
      * @return
      */
-    @InterceptorIgnore(dataPermission = "true")
+    @InterceptorIgnore(tenantLine = "true")
     UserDTO get(@Param(Constants.WRAPPER) Wrapper queryWrapper);
 
+    /**
+     * 根据条件查询用户
+     *
+     * @param queryWrapper
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    UserDTO getFlowAbleById(@Param(Constants.WRAPPER) Wrapper queryWrapper);
+
     @InterceptorIgnore(tenantLine = "true")
     int updateById(@Param("et") User entity);
 
@@ -89,6 +98,15 @@ public interface UserMapper extends BaseMapper <User> {
     List <UserDTO> findListByPostId(@Param("postId") String postId);
 
     /**
+     * 按岗位获取用户列表
+     *
+     * @param postId
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    List <UserDTO> findListFlowAbleByPostId(@Param("postId") String postId);
+
+    /**
      * 删除用户角色关联数据
      *
      * @param userId

+ 36 - 10
jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/mapper/xml/UserMapper.xml

@@ -94,6 +94,25 @@
         ${ew.customSqlSegment}
     </select>
 
+    <!-- 获得用户 -->
+    <select id="getFlowAbleById" resultMap="userResult">
+        SELECT
+        <include refid="userColumns"/>,
+        r.id AS "roleDTO.id",
+        r.name AS "roleDTO.name",
+        r.en_name AS "roleDTO.enname",
+        p.id AS "postDTO.id",
+        p.code AS "postDTO.code",
+        p.name AS "postDTO.name"
+        FROM sys_user a
+        <include refid="userJoins"/>
+        LEFT JOIN sys_user_role ur ON ur.user_id = a.id
+        LEFT JOIN sys_role r ON r.id = ur.role_id
+        LEFT JOIN sys_user_post up ON up.user_id = a.id
+        LEFT JOIN sys_post p ON p.id = up.post_id
+        ${ew.customSqlSegment}
+    </select>
+
 
     <!-- 分页查询用户信息 -->
     <select id="findList" resultMap="userResult">
@@ -108,19 +127,11 @@
     <!-- 分页查询用户信息 -->
     <select id="findList2" resultMap="userResult">
         SELECT
-        <include refid="userColumns"/>,
-        r.id AS "roleDTO.id",
-        r.name AS "roleDTO.name",
-        r.en_name AS "roleDTO.enname",
-        p.id AS "postDTO.id",
-        p.name AS "postDTO.name"
+        <include refid="userColumns"/>
         FROM sys_user a
         <include refid="userJoins"/>
-        LEFT JOIN sys_user_role ur ON ur.user_id = a.id
-        LEFT JOIN sys_role r ON r.id = ur.role_id
-        LEFT JOIN sys_user_post up ON up.user_id = a.id
-        LEFT JOIN sys_post p ON p.id = up.post_id
         ${ew.customSqlSegment}
+        and (a.is_admin is null or a.is_admin = '' or a.is_admin != 1)
     </select>
 
     <!-- 查询角色下的用户 -->
@@ -151,6 +162,21 @@
             p.id = #{postId} and a.del_flag = 0
         </where>
     </select>
+
+    <!-- 查询岗位下的用户 -->
+    <select id="findListFlowAbleByPostId" resultMap="userResult">
+        SELECT
+        <include refid="userColumns"/>,
+        p.id AS "postDTO.id",
+        p.name AS "postDTO.name"
+        FROM sys_user a
+        <include refid="userJoins"/>
+        LEFT JOIN sys_user_post up ON up.user_id = a.id
+        LEFT JOIN sys_post p ON p.id = up.post_id
+        <where>
+            p.id = #{postId} and a.del_flag = 0
+        </where>
+    </select>
     <select id="getUserByName" resultType="com.jeeplus.sys.service.dto.UserDTO">
 select a.id, a.company_id as "companyDTO.id", a.office_id as "officeDTO.id", a.login_name as "loginName",
 		a.password,

+ 22 - 0
jeeplus-modules/jeeplus-system/src/main/java/com/jeeplus/sys/service/UserService.java

@@ -89,6 +89,19 @@ public class UserService extends ServiceImpl <UserMapper, User> {
     }
 
     /**
+     * 获取用户
+     *
+     * @param id
+     * @return
+     */
+    public UserDTO getFlowAbleById(String id) {
+        QueryWrapper queryWrapper = new QueryWrapper ( );
+        queryWrapper.eq ( "a.id", id );
+        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); // 排除已经删除
+        return userMapper.getFlowAbleById ( queryWrapper );
+    }
+
+    /**
      * 根据登录名获取用户
      *
      * @param loginName
@@ -169,8 +182,17 @@ public class UserService extends ServiceImpl <UserMapper, User> {
      */
     public List <UserDTO> findListByPostId(String postId) {
         return baseMapper.findListByPostId ( postId );
+    }
 
 
+    /**
+     * 查询岗位下关联的用户
+     *
+     * @param postId
+     * @return
+     */
+    public List <UserDTO> findListFlowAbleByPostId(String postId) {
+        return baseMapper.findListFlowAbleByPostId ( postId );
     }
 
 

+ 2 - 0
jeeplus-modules/jeeplus-system/src/main/resources/bootstrap.yml

@@ -19,6 +19,8 @@ server:
 
 # Spring
 spring:
+  main:
+    allow-bean-definition-overriding: true
   application:
     # 应用名称
     name: jeeplus-system