Compare commits

...

8 Commits

Author SHA1 Message Date
furongxin
0a412a3da3 Merge remote-tracking branch 'znkj/dev' into frx 2024-09-14 14:41:24 +08:00
furongxin
7ac6fbade0 新增分配任务责任人领导的脚本逻辑
在流程定义中,扩展了任务分配规则,包括新的脚本LEADER_X7,该脚本被设计为分配任务给入职部门的领导。此更新涉及修改BpmTaskRuleScriptEnum,以支持新的任务分配需求,并实现相应的脚本处理类BpmTaskEntryLeaderScript来计算任务的候选用户。
2024-09-14 14:41:17 +08:00
furongxin
983b743ba9 移除 多余引用 2024-09-14 11:19:10 +08:00
furongxin
f8cfc157b1 refactor(job): 将外勤打卡权限变更逻辑移至FieldworkJob
将外勤打卡权限变更逻辑从BirthdayJob中提取并移至新的FieldworkJob,以专注于特定的定时任务职责。此更改通过在FieldworkJob中实施相同的逻辑,实现了定时任务的细分和清晰的责任分离。
2024-09-14 11:17:17 +08:00
furongxin
84a197b3a5 ```修复生日提醒任务并添加外勤打卡权限变更功能
修复了生日提醒任务中的问题,该问题之前未向特定人员发送提醒。此外,新增了外勤打卡权限变更功能,该功能根据用户是否需要进行外勤打卡,动态设置外勤打卡权限。包含对参数解析和用户信息获取的逻辑,以确保正确执行任务。
```
2024-09-14 11:00:09 +08:00
furongxin
b2effbec4e 新增未读日志数量查询接口及服务实现
在系统模块的作业日志功能中,新增了一个获取当前登录用户可查看日志未读数量的接口。该接口通过调用LogReadService的新方法`getUnRead`来获取未读日志的数量。服务端的实现通过查询数据库中用户的阅读状态,统计出未读日志的数量并返回。
2024-09-14 10:59:58 +08:00
furongxin
e8d15070c2 ```在BpmOAGoOutApi和BpmOAGoOutApiImpl中添加@PermitAll注解,以允许所有用户获取外出用户编号信息。
```
2024-09-14 10:59:39 +08:00
furongxin
38bfdf7328 ```日志实例查询优化:默认按时间降序排列
在日志实例的分页查询中,添加了默认按时间降序排序的逻辑。此改动确保在未指定排序方向时,返回的结果集按照最近的时间在前展示。```
2024-09-13 22:51:10 +08:00
10 changed files with 219 additions and 7 deletions

View File

@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import javax.annotation.security.PermitAll;
import java.util.List;
import java.util.Map;
@ -18,5 +19,6 @@ public interface BpmOAGoOutApi {
@GetMapping(PREFIX + "/getGoOutByTime")
@Operation(summary = "获取当日以及昨日外出的用户编号")
@PermitAll
CommonResult<Map<String, List<Long>>> getLeaveListByTime();
}

View File

@ -20,7 +20,8 @@ public enum BpmTaskRuleScriptEnum {
LEADER_X3(22L, "流程发起人的三级领导"),
LEADER_X4(23L, "审批人的一级领导"),
LEADER_X5(24L, "调岗部门领导"),
LEADER_X6(25L, "分配任务的责任人");
LEADER_X6(25L, "分配任务的责任人"),
LEADER_X7(26L, "入职部门领导");
/**
* 脚本编号

View File

@ -7,6 +7,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
@ -30,6 +31,7 @@ public class BpmOAGoOutApiImpl implements BpmOAGoOutApi{
private BpmOAGoOutService goOutService;
@Override
@PermitAll
public CommonResult<Map<String, List<Long>>> getLeaveListByTime() {
// 定义格式化模式

View File

@ -0,0 +1,69 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAEntryDO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAEntryService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.context.annotation.Lazy;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static java.util.Collections.emptySet;
public class BpmTaskEntryLeaderScript implements BpmTaskAssignScript {
@Resource
private DeptApi deptApi;
@Resource
private BpmOAEntryService entryService;
@Resource
@Lazy // 解决循环依赖
private BpmProcessInstanceService bpmProcessInstanceService;
@Resource
@Lazy // 解决循环依赖
private BpmTaskService bpmTaskService ;
@Override
public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) {
// 获得发起人
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
List<BpmTaskRespVO> bpmTaskRespVOs = bpmTaskService.getTaskListByProcessInstanceId(processInstance.getProcessInstanceId());
if (CollUtil.isEmpty(bpmTaskRespVOs)) {
return emptySet();
}
//根据流程实例ID 取到调岗流程表单
BpmOAEntryDO entryDO = entryService.getEntryByProcessInstanceId(processInstance.getProcessInstanceId());
//获取调岗部门ID
Long deptId = entryDO.getEntryDeptId();
//根据部门ID 获取部门信息
DeptRespDTO dept = deptApi.getDept(deptId).getCheckedData();
if (dept.getLevel() > 3) { //判断部门层级
String [] flag = dept.getFlag().split("-");
dept = deptApi.getDept(Long.valueOf(flag[3])).getCheckedData();
}
return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet();
}
@Override
public BpmTaskRuleScriptEnum getEnum() {
return BpmTaskRuleScriptEnum.LEADER_X7;
}
}

View File

@ -209,6 +209,14 @@ public class LogInstanceController {
return success(readUserVO);
}
@GetMapping("/get-unRead")
@Operation(summary = "获取当前登录用户可查看日志未读的数量")
@PreAuthorize("@ss.hasPermission('system:view-log:query')")
public CommonResult<Long> unRead() {
return success(logReadService.getUnRead(getLoginUserId()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出日志实例 Excel")
@PreAuthorize("@ss.hasPermission('system:log-instance:export')")

View File

@ -62,7 +62,7 @@ public interface LogInstanceMapper extends BaseMapperX<LogInstanceDO> {
queryWrapper.inIfPresent(LogInstanceDO::getStartUserId, userIds);
}
return selectPage(reqVO, queryWrapper);
return selectPage(reqVO, queryWrapper.orderByDesc(LogInstanceDO::getTime));
}

View File

@ -1,11 +1,19 @@
package cn.iocoder.yudao.module.system.job.birthday;
import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi;
import cn.iocoder.yudao.module.system.convert.notice.NoticeConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobContext;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
@ -14,16 +22,27 @@ import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@Component
@Slf4j
@EnableScheduling
public class BirthdayJob {
@Resource
private AdminUserMapper adminUserMapper;
@Resource
private AdminUserService userService;
@Resource
private PermissionService permissionService;
@Resource
private SubscribeMessageSendApi subscribeMessageSendApi;
/**
* 生日提醒
*
@ -32,15 +51,44 @@ public class BirthdayJob {
@XxlJob("birthdayJob")
@TenantJob // --- 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意
public ReturnT<String> execute() {
// 生日提醒
birthdayRemind();
// 返回执行成功
return ReturnT.SUCCESS;
}
private void birthdayRemind() {
String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM-dd"));
// -- 获取当天月日 生日的人员列表
List<AdminUserDO> list = adminUserMapper.selectList(new LambdaQueryWrapper<AdminUserDO>()
.like(AdminUserDO::getBirthdayDay, time));
if (!list.isEmpty()) {
// TODO: 2024/9/2 发送短信未指定人
log.info("生日提醒,生日为{},人员为{}", time, list);
}
// 返回执行成功
return ReturnT.SUCCESS;
//获取参数
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
String jobParam = xxlJobContext.getJobParam();
if (!StringUtil.isNullOrEmpty(jobParam)) {
// 解析参数
JSONObject object = new JSONObject(jobParam);
Long roleId = object.getLong("roleId");
Set<Long> userIds = permissionService.getUserRoleIdListByRoleId(CollectionUtils.singleton(roleId));
//获得用户组中 用户信息
List<AdminUserDO> userDOs = userService.getUserList(userIds);
for (AdminUserDO adminUserDO : userDOs) {
if( adminUserDO.getOpenId() != null && !adminUserDO.getOpenId().isEmpty()) {
subscribeMessageSendApi.sendCompanyNotice(NoticeConvert.INSTANCE.convertBirthday(
adminUserDO.getOpenId(), "formal"));
}
}
log.info("生日提醒,生日为{},人员为{}", time, convertList(list, AdminUserDO::getNickname));
}
}
}
}

View File

@ -0,0 +1,67 @@
package cn.iocoder.yudao.module.system.job.fieldwork;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.bpm.api.oa.BpmOAGoOutApi;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Component
@Slf4j
@EnableScheduling
public class FieldworkJob {
@Resource
private AdminUserMapper adminUserMapper;
@Resource
private BpmOAGoOutApi goOutApi;
/**
* 外勤打卡权限调整 针对外出申请流程
*/
@XxlJob("fieldworkJob")
@TenantJob // --- 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意
public ReturnT<String> execute() {
// 外勤打卡权限变更
try {
// 获取用户编号
Map<String, List<Long>> goOutList = goOutApi.getLeaveListByTime().getCheckedData();
if (CollectionUtil.isNotEmpty(goOutList.get("now"))) {
// 讲需要当天外出的用户设置外勤打卡权限
adminUserMapper.update(new AdminUserDO().setFieldworkFlag(1).setFieldworkType(2),
new LambdaQueryWrapper<AdminUserDO>()
.in(AdminUserDO::getId, goOutList.get("now"))
.ne(AdminUserDO::getFieldworkType, 1));
}
if (CollectionUtil.isNotEmpty(goOutList.get("yesterday"))) {
// 将昨日外出的用户关闭外勤打卡权限
adminUserMapper.update(new AdminUserDO().setFieldworkFlag(0).setFieldworkType(0),
new LambdaQueryWrapper<AdminUserDO>()
.in(AdminUserDO::getId, goOutList.get("yesterday"))
.eq(AdminUserDO::getFieldworkType, 2));
}
}catch (Exception ex) {
log.info(ex.toString());
}
// 返回执行成功
return ReturnT.SUCCESS;
}
}

View File

@ -49,4 +49,11 @@ public interface LogReadService {
* @return 阅读状态
*/
Boolean isReadByLogId(Long logId);
/**
* 获取当前登录用户可查看日志未读的数量
* @param userId 用户编号
* @return 未读数量
*/
Long getUnRead(Long userId);
}

View File

@ -86,4 +86,12 @@ public class LogReadServiceImpl implements LogReadService{
return count > 0L;
}
@Override
public Long getUnRead(Long userId) {
return logReadMapper.selectCount(new LambdaQueryWrapperX<LogReadDo>()
.eq(LogReadDo::getReadUserId, userId)
.eq(LogReadDo::getReadStatus, 0));
}
}