Merge branch 'dev' of http://47.97.8.94:19527/yj/zn-cloud into dev
This commit is contained in:
commit
8078d05095
@ -16,7 +16,8 @@ public enum BpmMessageEnum {
|
||||
PROCESS_INSTANCE_REJECT("bpm_process_instance_reject"), // 流程任务被审批不通过时,发送给申请人
|
||||
TASK_ASSIGNED("bpm_task_assigned"), // 任务被分配时,发送给审批人
|
||||
BPM_WORK_TASK("bpm_work_task"), //【任务分配】发起任务
|
||||
BPM_WORK_TASK_COMPLETE("bpm_work_task_complete"); //【任务分配】任务完成
|
||||
BPM_WORK_TASK_COMPLETE("bpm_work_task_complete"), //【任务分配】任务完成
|
||||
BPM_OA_ENTRY_MESSAGE("bpm_oa_entry_message"); // 【入职申请】消息通知
|
||||
|
||||
/**
|
||||
* 短信模板的标识
|
||||
|
@ -1,11 +1,15 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.entry.BpmOAEntryCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.entry.BpmOAEntryRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAEntryConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAEntryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAEntryService;
|
||||
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.PostApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
@ -19,6 +23,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@ -42,6 +47,9 @@ public class BpmOAEntryController {
|
||||
@Resource
|
||||
private PostApi postApi;
|
||||
|
||||
@Resource
|
||||
private BpmTaskService bpmTaskService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建请求申请")
|
||||
@PermitAll
|
||||
@ -66,13 +74,24 @@ public class BpmOAEntryController {
|
||||
@PermitAll
|
||||
public CommonResult<BpmOAEntryRespVO> getEntryByOpenId(@RequestParam("openId") String openId) {
|
||||
|
||||
BpmOAEntryDO entry = entryService.getEntryByOpenId(openId);
|
||||
// 查询当前openId 是否存在
|
||||
List<BpmOAEntryDO> entryList = entryService.getEntryByOpenId(openId);
|
||||
|
||||
if (entry == null) {
|
||||
if (CollectionUtil.isEmpty(entryList)) {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
BpmOAEntryDO entry = entryList.get(0);
|
||||
BpmOAEntryRespVO respVO = BpmOAEntryConvert.INSTANCE.convert(entry);
|
||||
if (entry.getResult().equals(BpmProcessInstanceResultEnum.REJECT.getResult())) {
|
||||
|
||||
// 获得取消流程的 task
|
||||
BpmTaskExtDO taskExtDO = bpmTaskService.getTaskByProcessInstanceIdAndResult(entry.getProcessInstanceId(),
|
||||
BpmProcessInstanceResultEnum.REJECT.getResult());
|
||||
|
||||
respVO.setRemark(taskExtDO.getReason());
|
||||
}
|
||||
|
||||
// 设备部门名称
|
||||
respVO.setEntryDeptName(getDept(entry.getEntryDeptId()).getName());
|
||||
// 设备岗位名称
|
||||
@ -97,7 +116,7 @@ public class BpmOAEntryController {
|
||||
/**
|
||||
* 获得岗位信息
|
||||
* @param postId 岗位ID
|
||||
* @return
|
||||
* @return 岗位信息
|
||||
*/
|
||||
public PostRespVO getPost(Long postId) {
|
||||
|
||||
|
@ -62,4 +62,7 @@ public class BpmOAEntryRespVO extends BpmOABaseRespVO {
|
||||
|
||||
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<UploadUserFile> fileItems;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
}
|
||||
|
@ -5,16 +5,15 @@ import lombok.Data;
|
||||
|
||||
/**
|
||||
* 功能描述 用于给oa流程附件同用的上传文件对象
|
||||
*
|
||||
* @author: yj
|
||||
* @date: 2024年02月07日 22:37
|
||||
* author: yj
|
||||
* date: 2024年02月07日 22:37
|
||||
*/
|
||||
@Data
|
||||
public class UploadUserFile {
|
||||
|
||||
@Schema(description = "文件原始名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.jpg")
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文件URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx.xxx/xx/xx/123.jpgss")
|
||||
private String url;
|
||||
private String url;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.PostApi;
|
||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||
import cn.iocoder.yudao.module.system.api.equipment.UsersExtApi;
|
||||
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
|
||||
import cn.iocoder.yudao.module.system.api.sms.SmsSendApi;
|
||||
@ -15,7 +16,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableFeignClients(clients = {FileApi.class,RoleApi.class, DeptApi.class, PostApi.class, AdminUserApi.class, SmsSendApi.class, DictDataApi.class, NotifyMessageSendApi.class,
|
||||
SubscribeMessageSendApi.class, SocialClientApi.class
|
||||
SubscribeMessageSendApi.class, SocialClientApi.class, UsersExtApi.class
|
||||
})
|
||||
public class RpcConfiguration {
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.entry.BpmOAEntryCreate
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAEntryDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
public interface BpmOAEntryService {
|
||||
|
||||
@ -21,7 +22,7 @@ public interface BpmOAEntryService {
|
||||
* @param id 编号
|
||||
* @param result 结果
|
||||
*/
|
||||
void updateEntryResult(Long id, Integer result);
|
||||
void updateEntryResult(String processInstanceId, Long id, Integer result);
|
||||
|
||||
/**
|
||||
* 获得入职申请
|
||||
@ -36,5 +37,5 @@ public interface BpmOAEntryService {
|
||||
* @param openId openId
|
||||
* @return 入职申请信息
|
||||
*/
|
||||
BpmOAEntryDO getEntryByOpenId(String openId);
|
||||
List<BpmOAEntryDO> getEntryByOpenId(String openId);
|
||||
}
|
||||
|
@ -1,21 +1,41 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.string.DTO.IdCardDO;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.entry.BpmOAEntryCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.upload.UploadUserFile;
|
||||
import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert;
|
||||
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAEntryConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAEntryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAEntryMapper;
|
||||
import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.infra.api.file.dto.UserFileUpdateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.equipment.UsersExtApi;
|
||||
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.UserSaveRespDTO;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_ENTRY_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
@ -37,8 +57,28 @@ public class BpmOAEntryServiceImpl implements BpmOAEntryService{
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceApi processInstanceApi;
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private BpmProcessInstanceService bpmProcessInstanceService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi userApi;
|
||||
|
||||
@Resource
|
||||
private FileApi fileApi;
|
||||
|
||||
@Resource
|
||||
private UsersExtApi usersExtApi;
|
||||
|
||||
@Resource
|
||||
private WebProperties webProperties;
|
||||
|
||||
@Resource
|
||||
private NotifyMessageSendApi notifyMessageSendApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createEntry(BpmOAEntryCreateReqVO createReqVO) {
|
||||
|
||||
//插入OA 入职申请
|
||||
@ -59,16 +99,75 @@ public class BpmOAEntryServiceImpl implements BpmOAEntryService{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEntryResult(Long id, Integer result) {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateEntryResult(String processInstanceId, Long id, Integer result) {
|
||||
|
||||
validateLeaveExists(id);
|
||||
entryMapper.updateById(new BpmOAEntryDO().setId(id).setResult(result));
|
||||
BpmOAEntryDO entry = validateLeaveExists(id);
|
||||
|
||||
BpmOAEntryDO updateVO = new BpmOAEntryDO().setId(id).setResult(result);
|
||||
//审核通过 (最后节点)
|
||||
if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
|
||||
|
||||
ProcessInstance instance = bpmProcessInstanceService.getProcessInstance(processInstanceId);
|
||||
|
||||
if (instance.isEnded()) {
|
||||
|
||||
// 新增入职申请中的用户信息
|
||||
UserSaveRespDTO saveRespDTO = BeanUtils.toBean(entry, UserSaveRespDTO.class);
|
||||
saveRespDTO.setId(null);
|
||||
saveRespDTO.setDeptId(entry.getEntryDeptId());
|
||||
saveRespDTO.setPostIds(Collections.singleton(entry.getEntryPostId()));
|
||||
saveRespDTO.setPassword("123456");
|
||||
|
||||
// 解析身份证号码
|
||||
IdCardDO idCardDO = StrUtils.IdCardAnalysis(saveRespDTO.getIdcard());
|
||||
// 设置性别、年龄、生日
|
||||
saveRespDTO.setSex(idCardDO.getSex());
|
||||
saveRespDTO.setAge(idCardDO.getAge());
|
||||
saveRespDTO.setBirthdayDay(idCardDO.getDate());
|
||||
|
||||
// 插入用户 获得用户编号
|
||||
Long userId = userApi.createUser(saveRespDTO).getCheckedData();
|
||||
updateVO.setEntryUserId(userId);
|
||||
|
||||
// 同步修改用户文件数据
|
||||
List<UploadUserFile> uploadUserFiles = BeanUtils.toBean(entry.getFileItems(), UploadUserFile.class);
|
||||
UserFileUpdateReqDTO updateReqDTO = new UserFileUpdateReqDTO()
|
||||
.setUrls(convertList(uploadUserFiles, UploadUserFile::getUrl))
|
||||
.setUserId(userId);
|
||||
fileApi.updateUserFileUserId(updateReqDTO);
|
||||
|
||||
// 同步修改business_file文件 更新用户编号
|
||||
fileApi.updateBusinessFileFormEntry(entry.getFaceImg(), String.valueOf(userId));
|
||||
|
||||
try {
|
||||
// 同步插入用户拓展表
|
||||
usersExtApi.createUsersExt(userId, entry.getNickname(), entry.getEntryDeptId(), entry.getFaceImg());
|
||||
} catch (Exception e) {
|
||||
|
||||
Map<String, Object> templateParams = new HashMap<>();
|
||||
templateParams.put("userName", entry.getNickname());
|
||||
templateParams.put("detailUrl", webProperties.getAdminUi().getUrl() + "/attendance/user?userName=" + entry.getNickname());
|
||||
|
||||
// 发送站内信 通知流程发起人, 新员工人脸图片上传失败
|
||||
notifyMessageSendApi.sendSingleMessageToAdmin(BpmMessageConvert.INSTANCE.convert1(
|
||||
entry.getUserId(), BpmMessageEnum.BPM_OA_ENTRY_MESSAGE.getSmsTemplateCode(), templateParams));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新入职申请状态
|
||||
entryMapper.updateById(updateVO);
|
||||
}
|
||||
|
||||
private void validateLeaveExists(Long id) {
|
||||
if (entryMapper.selectById(id) == null) {
|
||||
private BpmOAEntryDO validateLeaveExists(Long id) {
|
||||
|
||||
BpmOAEntryDO entry = entryMapper.selectById(id);
|
||||
if (entry == null) {
|
||||
throw exception(OA_ENTRY_NOT_EXISTS);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,10 +177,10 @@ public class BpmOAEntryServiceImpl implements BpmOAEntryService{
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmOAEntryDO getEntryByOpenId(String openId) {
|
||||
public List<BpmOAEntryDO> getEntryByOpenId(String openId) {
|
||||
|
||||
return entryMapper.selectOne(new LambdaQueryWrapperX<BpmOAEntryDO>()
|
||||
return entryMapper.selectList(new LambdaQueryWrapperX<BpmOAEntryDO>()
|
||||
.eq(BpmOAEntryDO::getOpenId, openId)
|
||||
.eq(BpmOAEntryDO::getResult, BpmProcessInstanceResultEnum.REJECT.getResult()));
|
||||
.orderByDesc(BpmOAEntryDO::getCreateTime));
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,6 @@ public class BpmOAEntryResultListener extends BpmProcessInstanceResultEventListe
|
||||
@Override
|
||||
protected void onEvent(BpmProcessInstanceResultEvent event) {
|
||||
|
||||
entryService.updateEntryResult(Long.parseLong(event.getBusinessKey()), event.getResult());
|
||||
entryService.updateEntryResult(event.getId(), Long.parseLong(event.getBusinessKey()), event.getResult());
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -205,5 +205,19 @@ public interface BpmTaskService {
|
||||
*/
|
||||
String getCurrentTaskIdByProcessInstanceId(String processInstanceId) ;
|
||||
|
||||
/**
|
||||
* 获得指定的task记录
|
||||
* @param processInstanceId 流程实例id集合
|
||||
* @param result 结果
|
||||
* @return task
|
||||
*/
|
||||
List<BpmTaskExtDO> getTaskByProcessInstanceIdAndResult(List<String> processInstanceId, Integer result);
|
||||
|
||||
/**
|
||||
* 获得指定的task记录
|
||||
* @param processInstanceId 流程实例id
|
||||
* @param result 结果
|
||||
* @return task
|
||||
*/
|
||||
BpmTaskExtDO getTaskByProcessInstanceIdAndResult(String processInstanceId, Integer result);
|
||||
}
|
||||
|
@ -1235,4 +1235,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
|
||||
return taskExtMapper.selectTask(processInstanceId, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmTaskExtDO getTaskByProcessInstanceIdAndResult(String processInstanceId, Integer result) {
|
||||
|
||||
return taskExtMapper.selectOne(new LambdaQueryWrapperX<BpmTaskExtDO>()
|
||||
.eq(BpmTaskExtDO::getProcessInstanceId, processInstanceId)
|
||||
.eq(BpmTaskExtDO::getResult, result));
|
||||
}
|
||||
}
|
||||
|
@ -74,14 +74,20 @@ public interface FileApi {
|
||||
String updateBusinessFileContent(@RequestParam("url") String url,
|
||||
@RequestParam("businessType") Long businessType,
|
||||
@RequestParam("name") String name,
|
||||
@RequestBody byte[] content) ;
|
||||
@RequestBody byte[] content);
|
||||
|
||||
@PostMapping(PREFIX + "/updateBusinessFile")
|
||||
@Operation(summary = "修改BusinessFile文件中的 businessInstanceId | 入职申请用")
|
||||
CommonResult<Boolean> updateBusinessFileFormEntry(@RequestParam("url") String url,
|
||||
@RequestParam("businessInstanceId") String businessInstanceId);
|
||||
|
||||
|
||||
@DeleteMapping(PREFIX + "/deleteBpmFile")
|
||||
@Operation(summary = "删除工作流附件")
|
||||
@Parameter(name = "url", description = "附件URL地址", required = true)
|
||||
CommonResult<Boolean> deleteBpmFile(@RequestParam("url") String url) throws Exception;
|
||||
|
||||
@PutMapping(PREFIX + "/updateUserFile")
|
||||
@PostMapping(PREFIX + "/updateUserFile")
|
||||
@Operation(summary = "修改用户文件绑定 用户编号")
|
||||
CommonResult<Boolean> updateUserFileUserId(@RequestBody UserFileUpdateReqDTO updateReqVO);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.infra.api.file.dto.UserFileUpdateReqDTO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.BpmFileUploadReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.UserFileUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileService;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@ -55,6 +56,14 @@ public class FileApiImpl implements FileApi {
|
||||
return fileService.updateBusinessFileContent(url, businessType, name, content) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public CommonResult<Boolean> updateBusinessFileFormEntry(String url, String businessInstanceId) {
|
||||
|
||||
fileService.uploadBusinessFileFormEntry(url, businessInstanceId);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> deleteBpmFile(String url) throws Exception {
|
||||
|
||||
|
@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.*;
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileService;
|
||||
@ -35,6 +36,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@ -61,6 +63,9 @@ public class FileController {
|
||||
@Resource
|
||||
private PostApi postApi;
|
||||
|
||||
@Resource
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
@PostMapping("/uploadBpmFileProcessInstanceId")
|
||||
@Operation(summary = "更新文件的流程实例ID")
|
||||
@OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
|
||||
@ -185,37 +190,45 @@ public class FileController {
|
||||
@Parameter(name = "deptId", description = "部门编号", required = true, example = "1024")
|
||||
@Parameter(name = "postId", description = "岗位编号", example = "1024")
|
||||
public CommonResult<QRCodeDO> createQRCode(@RequestParam("userId") Long userId,
|
||||
@RequestParam("deptId") Long deptId,
|
||||
@RequestParam(value = "postId", required = false) Long postId) {
|
||||
@RequestParam("deptId") Long deptId,
|
||||
@RequestParam(value = "postId", required = false) Long postId) {
|
||||
|
||||
|
||||
|
||||
// 查询当前部门编号下 是否存在小程序码
|
||||
QRCodeDO qrCodeDO = fileService.getQRCode(deptId);
|
||||
QRCodeDO qrCodeDO = fileService.getQRCode(deptId, null);
|
||||
|
||||
JSONObject scene = new JSONObject();
|
||||
scene.set("userId", userId);
|
||||
scene.set("deptId", deptId);
|
||||
scene.set("postId", postId);
|
||||
|
||||
// 小程序码不存在,则 生成新的小程序码
|
||||
if (qrCodeDO == null) {
|
||||
|
||||
// 生成小程序码
|
||||
File QRCode = socialClientApi.getQRCode("subPages/register/register", "deptId=" + deptId).getCheckedData();
|
||||
|
||||
JSONObject object = new JSONObject();
|
||||
object.set("userId", userId);
|
||||
object.set("deptId", deptId);
|
||||
object.set("postId", postId);
|
||||
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(QRCode);
|
||||
byte[] content = IoUtil.readBytes(fis);
|
||||
|
||||
// 上传小程序码 获得url
|
||||
qrCodeDO = fileService.createQRCodeFile(deptId, QRCode.getName(), content, object.toString());
|
||||
qrCodeDO = createQRCode(deptId, scene.toString());
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
return error(OA_QRCODE_ERROR);
|
||||
}
|
||||
}else { // 存在的时候, 则更新小程序码的生成时间
|
||||
}else { // 存在的时候, 判断是否已存在相同参数的小程序码
|
||||
|
||||
fileService.updateQRCodeFile(qrCodeDO.getId());
|
||||
// 查询是否存在 参数一致的小程序码
|
||||
qrCodeDO = fileService.getQRCode(deptId, scene.toString());
|
||||
if (qrCodeDO == null) {
|
||||
|
||||
try {
|
||||
qrCodeDO = createQRCode(deptId, scene.toString());
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
return error(OA_QRCODE_ERROR);
|
||||
}
|
||||
}else {
|
||||
fileService.updateQRCodeFile(qrCodeDO.getId());
|
||||
}
|
||||
}
|
||||
|
||||
return success(qrCodeDO);
|
||||
@ -223,10 +236,11 @@ public class FileController {
|
||||
|
||||
@GetMapping("getQRCode")
|
||||
@Operation(summary = "获得入职申请小程序码")
|
||||
public CommonResult<QRCodeReqVO> getQRCode(@RequestParam("deptId") Long deptId) {
|
||||
@PermitAll
|
||||
public CommonResult<QRCodeReqVO> getQRCode(@RequestParam("id") Long id) {
|
||||
|
||||
// 查询当前部门编号下 是否存在小程序码
|
||||
QRCodeDO qrCodeDO = fileService.getQRCode(deptId);
|
||||
QRCodeDO qrCodeDO = fileService.getQRCode(id);
|
||||
|
||||
if (qrCodeDO != null) {
|
||||
|
||||
@ -239,6 +253,7 @@ public class FileController {
|
||||
reqVO.setUserId(Long.valueOf(qrCodeDO.getUpdater()));
|
||||
|
||||
// 获取部门信息
|
||||
Long deptId = Long.valueOf(scene.get("deptId").toString());
|
||||
DeptRespDTO deptRespDTO = deptApi.getDept(deptId).getCheckedData();
|
||||
reqVO.setDeptId(deptId);
|
||||
reqVO.setDeptName(deptRespDTO.getName());
|
||||
@ -267,4 +282,18 @@ public class FileController {
|
||||
|
||||
return success(true);
|
||||
}
|
||||
|
||||
public QRCodeDO createQRCode(Long deptId, String scene) throws FileNotFoundException {
|
||||
|
||||
Long id = fileService.createQRCodeFile(deptId, scene.toString());
|
||||
|
||||
// 生成小程序码
|
||||
File QRCode = socialClientApi.getQRCode("subPages/register/register", "id=" + id).getCheckedData();
|
||||
|
||||
FileInputStream fis = new FileInputStream(QRCode);
|
||||
byte[] content = IoUtil.readBytes(fis);
|
||||
|
||||
// 上传小程序码 获得url
|
||||
return fileService.updateQRCodeFile(id, deptId, QRCode.getName(), content);
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,11 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper
|
||||
public interface QRCodeDOMapper extends BaseMapperX<QRCodeDO> {
|
||||
|
||||
default QRCodeDO selectByDeptId(Long deptId) {
|
||||
default QRCodeDO selectByDeptId(Long deptId, String scene) {
|
||||
|
||||
return selectOne(new LambdaQueryWrapperX<QRCodeDO>()
|
||||
.eq(QRCodeDO::getBusinessId, deptId)
|
||||
.eqIfPresent(QRCodeDO::getScene, scene)
|
||||
.eq(QRCodeDO::getBusinessType, 1));
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +102,12 @@ public interface FileService {
|
||||
*/
|
||||
void uploadBusinessFileProcessInstanceId(BusinessFileUploadReqVO reqVO) throws Exception ;
|
||||
|
||||
/**
|
||||
* 更新文件的流程实例ID | 入职申请用
|
||||
* @param url 文件地址
|
||||
*/
|
||||
void uploadBusinessFileFormEntry(String url, String businessInstanceId);
|
||||
|
||||
/**
|
||||
* 获取用户的签名图片地址
|
||||
*
|
||||
@ -153,14 +159,22 @@ public interface FileService {
|
||||
* @param content 字节流
|
||||
* @return url
|
||||
*/
|
||||
QRCodeDO createQRCodeFile(Long deptId, String name, byte[] content, String scene) ;
|
||||
QRCodeDO updateQRCodeFile(Long id, Long deptId, String name, byte[] content) ;
|
||||
|
||||
/**
|
||||
* 获得小程序码信息
|
||||
* @param id 编号
|
||||
* @return 小程序码信息
|
||||
*/
|
||||
QRCodeDO getQRCode(Long id);
|
||||
|
||||
/**
|
||||
* 获得小程序码信息
|
||||
* @param deptId 部门编号
|
||||
* @param scene 参数
|
||||
* @return 小程序码信息
|
||||
*/
|
||||
QRCodeDO getQRCode(Long deptId);
|
||||
QRCodeDO getQRCode(Long deptId, String scene);
|
||||
|
||||
/**
|
||||
* 更新 小程序码生成时间
|
||||
@ -173,4 +187,11 @@ public interface FileService {
|
||||
* @param url 文件链接
|
||||
*/
|
||||
void deleteQRCode(String url);
|
||||
|
||||
/**
|
||||
* 创建小程序码文件
|
||||
* @param deptId 部门编号
|
||||
* @param scene 参数
|
||||
*/
|
||||
Long createQRCodeFile(Long deptId, String scene);
|
||||
}
|
||||
|
@ -319,7 +319,6 @@ public class FileServiceImpl implements FileService {
|
||||
/**
|
||||
* 更新文件的流程实例ID
|
||||
* @param reqVO
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@ -333,6 +332,21 @@ public class FileServiceImpl implements FileService {
|
||||
businessFileMapper.update(null, lambdaUpdateWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void uploadBusinessFileFormEntry(String url, String businessInstanceId) {
|
||||
|
||||
LambdaUpdateWrapper<BusinessFileDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
|
||||
lambdaUpdateWrapper.eq(BusinessFileDO::getUrl, url);
|
||||
lambdaUpdateWrapper.set(BusinessFileDO::getBusinessInstanceId, businessInstanceId); // 假设 bid 是要更新的 bid 值
|
||||
lambdaUpdateWrapper.set(BusinessFileDO::getUploadUserId, businessInstanceId);
|
||||
lambdaUpdateWrapper.set(BusinessFileDO::getCreator, businessInstanceId);
|
||||
lambdaUpdateWrapper.set(BusinessFileDO::getUpdater, businessInstanceId);
|
||||
|
||||
// 调用 MyBatis Plus 的 update 方法执行批量更新
|
||||
businessFileMapper.update(null, lambdaUpdateWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserSignImgPath(Long userId) {
|
||||
BusinessFileDO businessFileDO = businessFileMapper.selectOneByBusinessInstanceId(2L, userId.toString()) ;
|
||||
@ -472,7 +486,7 @@ public class FileServiceImpl implements FileService {
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public QRCodeDO createQRCodeFile(Long deptId, String name, byte[] content, String scene) {
|
||||
public QRCodeDO updateQRCodeFile(Long id, Long deptId, String name, byte[] content) {
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
// 计算默认的 path 名
|
||||
@ -491,20 +505,25 @@ public class FileServiceImpl implements FileService {
|
||||
|
||||
// 插入 system_qr_code
|
||||
QRCodeDO fileDo = new QRCodeDO();
|
||||
fileDo.setBusinessId(deptId.toString());
|
||||
fileDo.setId(id);
|
||||
fileDo.setBusinessType(1);
|
||||
fileDo.setConfigId(client.getId());
|
||||
fileDo.setUrl(url);
|
||||
fileDo.setScene(scene);
|
||||
qrCodeDOMapper.insert(fileDo);
|
||||
qrCodeDOMapper.updateById(fileDo);
|
||||
|
||||
return fileDo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QRCodeDO getQRCode(Long deptId) {
|
||||
public QRCodeDO getQRCode(Long id) {
|
||||
|
||||
return qrCodeDOMapper.selectByDeptId(deptId);
|
||||
return qrCodeDOMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QRCodeDO getQRCode(Long deptId, String scene) {
|
||||
|
||||
return qrCodeDOMapper.selectByDeptId(deptId, scene);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -533,6 +552,17 @@ public class FileServiceImpl implements FileService {
|
||||
qrCodeDOMapper.deleteById(qrCodeDO.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createQRCodeFile(Long deptId, String scene) {
|
||||
|
||||
QRCodeDO createDO = new QRCodeDO()
|
||||
.setBusinessId(String.valueOf(deptId))
|
||||
.setScene(scene);
|
||||
|
||||
qrCodeDOMapper.insert(createDO);
|
||||
return createDO.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从文件存储器删除 文件
|
||||
*/
|
||||
|
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.system.api.equipment;
|
||||
|
||||
import cn.iocoder.yudao.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||
@Tag(name = "RPC 服务 - 用户拓展")
|
||||
public interface UsersExtApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/attendance-machine";
|
||||
|
||||
@PostMapping(PREFIX + "/create")
|
||||
@Operation(summary = "新增设备请求记录")
|
||||
void createUsersExt(@RequestParam("userId") Long userId,
|
||||
@RequestParam("userName") String userName,
|
||||
@RequestParam("deptId") Long deptId,
|
||||
@RequestParam("faceImg") String faceImg);
|
||||
}
|
@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.system.api.user;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.UserSaveRespDTO;
|
||||
import cn.iocoder.yudao.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.Collection;
|
||||
@ -63,4 +66,8 @@ public interface AdminUserApi {
|
||||
@Operation(summary = "获取同部门所有用户id")
|
||||
@Parameter(name = "userId", description = "用户id", example = "1024", required = true)
|
||||
CommonResult<List<Long>> getUserIdsByUserIdGroupByDept(@RequestParam("userId") Long userId);
|
||||
|
||||
@PostMapping(PREFIX + "/create")
|
||||
@Operation(summary = "创建用户")
|
||||
CommonResult<Long> createUser(@RequestBody UserSaveRespDTO saveRespDTO);
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
package cn.iocoder.yudao.module.system.api.user.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.IdCard;
|
||||
import cn.iocoder.yudao.framework.common.validation.Mobile;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
@Schema(description = "RPC 服务 - Admin 用户创建 DTO")
|
||||
@Data
|
||||
public class UserSaveRespDTO {
|
||||
|
||||
@Schema(description = "用户 ID", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@Size(max = 30, message = "用户昵称长度不能超过30个字符")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "部门ID", example = "我是一个用户")
|
||||
private Long deptId;
|
||||
|
||||
@Schema(description = "岗位编号数组", example = "1")
|
||||
private Set<Long> postIds;
|
||||
|
||||
@Schema(description = "手机号码", example = "15601691300")
|
||||
@Mobile
|
||||
private String mobile;
|
||||
|
||||
@Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "身份证号码")
|
||||
@IdCard
|
||||
private String idcard;
|
||||
|
||||
@Schema(description = "年龄", example = "23")
|
||||
private Integer age;
|
||||
|
||||
@Schema(description = "生日日期", example = "03-23")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate birthdayDay;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package cn.iocoder.yudao.module.system.api.equipment;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket.AddUserVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.equipment.AttendanceMachineDO;
|
||||
import cn.iocoder.yudao.module.system.service.equipment.AttendanceMachineService;
|
||||
import cn.iocoder.yudao.module.system.service.equipment.UsersExtService;
|
||||
import cn.iocoder.yudao.module.system.service.websocket.WebsocketService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
public class UsersExtApiImpl implements UsersExtApi{
|
||||
|
||||
@Resource
|
||||
private UsersExtService usersExtService;
|
||||
|
||||
@Resource
|
||||
private AttendanceMachineService attendanceMachineService;
|
||||
|
||||
@Resource
|
||||
private WebsocketService websocketService;
|
||||
|
||||
@Override
|
||||
public void createUsersExt(Long userId, String userName, Long deptId, String faceImg) {
|
||||
|
||||
// 查询当前部门下 是否存在考勤设备
|
||||
List<AttendanceMachineDO> deviceList = attendanceMachineService.getListByDeptId(deptId);
|
||||
List<String> deviceNos = new ArrayList<>();
|
||||
try {
|
||||
|
||||
for (AttendanceMachineDO machineDO : deviceList) {
|
||||
|
||||
// 设置下发命令
|
||||
AddUserVO addUserVO = new AddUserVO()
|
||||
.setCmd("addUser")
|
||||
.setUser_id(String.valueOf(userId))
|
||||
.setName(userName)
|
||||
.setFace_template(faceImg)
|
||||
.setId_valid("");
|
||||
|
||||
// 发送指令至 考勤设备 下发员工
|
||||
websocketService.sendSn(machineDO.getDeviceNo(), addUserVO, 1);
|
||||
|
||||
deviceNos.add(machineDO.getDeviceNo());
|
||||
}
|
||||
} finally {
|
||||
|
||||
UsersExtSaveReqVO saveReqVO = new UsersExtSaveReqVO()
|
||||
.setUserId(userId)
|
||||
.setDeptId(deptId)
|
||||
.setFaceImg(faceImg)
|
||||
.setAttendanceMachineNos(deviceNos);
|
||||
// 插入用户拓展信息
|
||||
usersExtService.createUsers(saveReqVO);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.UserSaveRespDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -12,7 +14,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
@ -62,4 +63,10 @@ public class AdminUserApiImpl implements AdminUserApi {
|
||||
return success(userIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Long> createUser(UserSaveRespDTO saveRespDTO) {
|
||||
|
||||
return success(userService.createUser(BeanUtils.toBean(saveRespDTO, UserSaveReqVO.class)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,9 +3,6 @@ package cn.iocoder.yudao.module.system.controller.admin.equipment.vo.attendancem
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 考勤设备新增/修改 Request VO")
|
||||
@Data
|
||||
public class AttendanceMachineSaveReqVO {
|
||||
@ -28,4 +25,7 @@ public class AttendanceMachineSaveReqVO {
|
||||
@Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String deviceName;
|
||||
|
||||
@Schema(description = "是否分配资产")
|
||||
private Boolean isAssets;
|
||||
|
||||
}
|
@ -91,7 +91,7 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService {
|
||||
validateAttendanceMachineExists(updateReqVO.getId(), updateReqVO.getDeviceNo());
|
||||
|
||||
//如果分配机构的情况, 则调用资产分配方法
|
||||
if (updateReqVO.getDeptId() != null) {
|
||||
if (updateReqVO.getIsAssets()) {
|
||||
|
||||
DeptAssetsInOutStockSaveReqVO vos = new DeptAssetsInOutStockSaveReqVO();
|
||||
vos.setInDeptId(updateReqVO.getDeptId());
|
||||
|
@ -66,7 +66,7 @@ public class WebsocketServiceImpl implements WebsocketService{
|
||||
if (StringUtil.isEmpty(stringRedisTemplate.opsForValue().get(deviceNo))) {
|
||||
stringRedisTemplate.opsForValue().set(deviceNo, "true");
|
||||
}
|
||||
// 发送修改密码命令给设备
|
||||
// 发送命令给设备
|
||||
webSocketSenderApi.sendSN(deviceNo, "attendance-message-send", JsonUtils.toJsonString(baseVO));
|
||||
|
||||
Long startTime = System.currentTimeMillis();
|
||||
|
@ -116,6 +116,12 @@ spring:
|
||||
# Spring Boot Admin Server 服务端的相关配置
|
||||
context-path: /admin # 配置 Spring
|
||||
|
||||
# 日志文件配置
|
||||
logging:
|
||||
level:
|
||||
# 配置自己写的 MyBatis Mapper 打印日志
|
||||
cn.iocoder.yudao.module.system.dal.mysql: debug
|
||||
|
||||
--- #################### 微信公众号、小程序相关配置 ####################
|
||||
wx:
|
||||
mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档
|
||||
|
Loading…
Reference in New Issue
Block a user