This commit is contained in:
aikai 2024-07-04 19:08:55 +08:00
commit 8078d05095
26 changed files with 460 additions and 60 deletions

View File

@ -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"); // 入职申请消息通知
/**
* 短信模板的标识

View File

@ -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) {

View File

@ -62,4 +62,7 @@ public class BpmOAEntryRespVO extends BpmOABaseRespVO {
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
private List<UploadUserFile> fileItems;
@Schema(description = "备注")
private String remark;
}

View File

@ -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;
}

View File

@ -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 {
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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());
}
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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();
}
/**
* 从文件存储器删除 文件
*/

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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)));
}
}

View File

@ -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;
}

View File

@ -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());

View File

@ -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();

View File

@ -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 文档