febs-common/febs-common-core/src/main/java/cc/mrbird/febs/common/core/constant/ModuleCode.java
New file @@ -0,0 +1,60 @@ package cc.mrbird.febs.common.core.constant; /** * name: ModuleCode * package: cc.mrbird.febs.common.core.constant * description: 系统模块码定义 * date: 2021-01-27 08:55 * * @author luoyibo * @version 0.1 * @since JDK 1.8 */ public class ModuleCode { /** * 系统框架-系统管理 */ public final static int FRAM_SYSTEM=1; /** * 系统框架-组织架构 */ public final static int FRAM_ORGANIC=2; /** * 系统框架-运营管理 */ public final static int FRAM_OPERATIONS=3; /** * 人力资源-组织规划 */ public final static int HR_ORGANIZATION=10; /** * 人力资源-招聘管理 */ public final static int HR_RECRUIT=11; /** * 人力资源-员工关系 */ public final static int HR_EMPLOYEE=12; /** * 人力资源-考勤管理 */ public final static int HR_ATTEND=13; /** * 人力资源-薪酬管理 */ public final static int HR_SALARY=14; /** * 人力资源-社保福利 */ public final static int HR_SOCIAL=15; /** * 人力资源-绩效管理 */ public final static int HR_PERFORMANCE=16; /** * 人力资源-培训开发 */ public final static int HR_TRAIN=17; } febs-common/febs-common-core/src/main/java/cc/mrbird/febs/common/core/utils/SequenceUtil.java
New file @@ -0,0 +1,196 @@ package cc.mrbird.febs.common.core.utils; import com.baomidou.mybatisplus.core.toolkit.SystemClock; import lombok.extern.slf4j.Slf4j; /** * name: SequenceUtil * package: cc.mrbird.febs.common.core.utils * description: 全局ID生成器,基于雪花算法 * 时间戳+机器码+系统码+序列号 * 时间戳:从2020-01-01开始的秒数 32位 * 机器码:5位 可有32台机器 * 系统码:6位 可设置64个系统 * 系统框架 * 系统管理 000000 1 * 组织架构 000001 2 * 运营管理000010 3 * Hr系统 * 组织规划 001010 10 * 招聘选拔 001011 11 * 员工关系 001100 12 * 考勤管理 001101 13 * 薪酬管理 001110 14 * 社保福利 001111 15 * 绩效管理 010000 16 * 培训开发 010001 17 * 序列号:10位,每秒1024个ID * date: 2021-01-27 20:39 * * @author luoyibo * @version 0.1 * @since JDK 1.8 */ @Slf4j public class SequenceUtil { /** * 初始偏移时间戳 */ private static final long OFFSET = 1546300800L; /** * 机器id */ private static long WORKER_ID; /** * 系统模块码 */ private static long MODULE_CODE; /** * 机器id所占位数 (5bit, 支持最大机器数 2^5 = 32) */ private static final long WORKER_ID_BITS = 5L; /** * 系统模块码所占位数 (6bit, 支持最大机器数 2^6 = 64) */ private static final long MODULE_CODE_BITS = 6L; /** * 自增序列所占位数 (10bit, 支持最大每秒生成 2^10 = 1024) */ private static final long SEQUENCE_ID_BITS = 10L; /** * 系统模块码偏移位数 */ private static final long MODULE_SHIFT_BITS = SEQUENCE_ID_BITS; /** * 机器id偏移位数 */ private static final long WORKER_SHIFT_BITS = SEQUENCE_ID_BITS + MODULE_CODE_BITS; /** * 自增序列偏移位数 */ private static final long OFFSET_SHIFT_BITS = SEQUENCE_ID_BITS + MODULE_CODE_BITS + WORKER_ID_BITS; /** * 机器标识最大值 (2^5 / 2 - 1 = 15) */ private static final long WORKER_ID_MAX = ((1 << WORKER_ID_BITS) - 1) >> 1; /** * 备份机器ID开始位置 (2^5 / 2 = 16) */ private static final long BACK_WORKER_ID_BEGIN = (1 << WORKER_ID_BITS) >> 1; /** * 系统模块码最大值 (2^6 - 1 = 63) */ private static final long MODULE_CODE_MAX = (1 << MODULE_CODE_BITS) - 1; /** * 自增序列最大值 (2^15 - 1 = 1023) */ private static final long SEQUENCE_MAX = (1 << SEQUENCE_ID_BITS) - 1; /** * 发生时间回拨时容忍的最大回拨时间 (秒) */ private static final long BACK_TIME_MAX = 1L; /** * 上次生成ID的时间戳 (秒) */ private static long lastTimestamp = 0L; /** * 当前秒内序列 (2^16) */ private static long sequence = 0L; /** * 备份机器上次生成ID的时间戳 (秒) */ private static long lastTimestampBak = 0L; /** * 备份机器当前秒内序列 (2^16) */ private static long sequenceBak = 0L; /** * 私有构造函数禁止外部访问 */ private SequenceUtil() { } /** * 获取自增序列 * * @return long */ public static long generateId(long workerId, long moduleCode) { WORKER_ID = workerId; MODULE_CODE = moduleCode; if (WORKER_ID > WORKER_ID_MAX || WORKER_ID < 0) { throw new IllegalArgumentException(String.format("机器数量范围: 0 ~ %d 目前: %d", WORKER_ID_MAX, workerId)); } if (MODULE_CODE > MODULE_CODE_MAX || MODULE_CODE < 0) { throw new IllegalArgumentException(String.format("模块数量范围: 0 ~ %d 目前: %d", MODULE_CODE_MAX, moduleCode)); } return nextId(SystemClock.now() / 1000); } /** * 主机器自增序列 * * @param timestamp 当前Unix时间戳 * @return long */ private static synchronized long nextId(long timestamp) { // 时钟回拨检查 if (timestamp < lastTimestamp) { // 发生时钟回拨 log.warn("时钟回拨, 启用备份机器ID: now: [{}] last: [{}]", timestamp, lastTimestamp); return nextIdBackup(timestamp); } // 开始下一秒 if (timestamp != lastTimestamp) { lastTimestamp = timestamp; sequence = 0L; } if (0L == (++sequence & SEQUENCE_MAX)) { sequence--; return nextIdBackup(timestamp); } return ((timestamp - OFFSET) << OFFSET_SHIFT_BITS) | (WORKER_ID << WORKER_SHIFT_BITS) | (MODULE_CODE << MODULE_SHIFT_BITS) | sequence; } /** * 备份机器自增序列 * * @param timestamp timestamp 当前Unix时间戳 * @return long */ private static long nextIdBackup(long timestamp) { int toSecond = 1000; if (timestamp < lastTimestampBak) { if (lastTimestampBak - SystemClock.now() / toSecond <= BACK_TIME_MAX) { timestamp = lastTimestampBak; } else { throw new RuntimeException(String.format("时钟回拨: now: [%d] last: [%d]", timestamp, lastTimestampBak)); } } if (timestamp != lastTimestampBak) { lastTimestampBak = timestamp; sequenceBak = 0L; } if (0L == (++sequenceBak & SEQUENCE_MAX)) { return nextIdBackup(timestamp + 1); } return ((timestamp - OFFSET) << OFFSET_SHIFT_BITS) | (WORKER_ID << WORKER_SHIFT_BITS) | (MODULE_CODE << MODULE_SHIFT_BITS) | sequence; } } febs-common/febs-common-datasource-starter/src/main/java/cc/mrbird/febs/common/datasource/starter/configure/FebsDataSourceAutoConfigure.java
@@ -3,6 +3,7 @@ import cc.mrbird.febs.common.datasource.starter.inteceptor.DataPermissionInterceptor; import com.baomidou.mybatisplus.core.parser.ISqlParser; import com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser; import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -38,4 +39,17 @@ paginationInterceptor.setSqlParserList(sqlParserList); return paginationInterceptor; } /** * * 注册乐观锁插件 * * date 2021-01-26 08:49 * @author: luoyibo * @return com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor */ @Bean @Order(-3) public OptimisticLockerInterceptor optimisticLockerInterceptor(){ return new OptimisticLockerInterceptor(); } } febs-server/febs-server-hr/src/main/java/cc/mrbird/febs/server/hr/controller/EmpBadRecordController.java
@@ -1,5 +1,7 @@ package cc.mrbird.febs.server.hr.controller; import cc.mrbird.febs.common.core.constant.ModuleCode; import cc.mrbird.febs.common.core.utils.SequenceUtil; import cc.mrbird.febs.server.hr.entity.EmpBadRecord; import cc.mrbird.febs.server.hr.service.IEmpBadRecordService; import cc.mrbird.febs.common.core.entity.FebsResponse; @@ -31,26 +33,30 @@ @RequiredArgsConstructor public class EmpBadRecordController { private final IEmpBadRecordService empBadrecordService; private final IEmpBadRecordService empBadRecordService; @GetMapping("sequence") public long getSequence(){ return SequenceUtil.generateId(0L,ModuleCode.HR_EMPLOYEE); } @GetMapping @PreAuthorize("hasAuthority('empBadrecord:list')") public FebsResponse getAllEmpBadrecords(EmpBadRecord empBadrecord) { return new FebsResponse().data(empBadrecordService.findEmpBadrecords(empBadrecord)); public FebsResponse getAllEmpBadRecords(EmpBadRecord empBadrecord) { return new FebsResponse().data(empBadRecordService.findEmpBadRecords(empBadrecord)); } @GetMapping("list") @PreAuthorize("hasAuthority('empBadrecord:list')") public FebsResponse empBadrecordList(QueryRequest request, EmpBadRecord empBadrecord) { Map<String, Object> dataTable = FebsUtil.getDataTable(this.empBadrecordService.findEmpBadrecords(request, empBadrecord)); public FebsResponse empBadRecordList(QueryRequest request, EmpBadRecord empBadrecord) { Map<String, Object> dataTable = FebsUtil.getDataTable(this.empBadRecordService.findEmpBadRecords(request, empBadrecord)); return new FebsResponse().data(dataTable); } @PostMapping @PreAuthorize("hasAuthority('empBadrecord:add')") public void addEmpBadrecord(@Valid EmpBadRecord empBadrecord) throws FebsException { public void addEmpBadRecord(@Valid EmpBadRecord empBadrecord) throws FebsException { try { this.empBadrecordService.createEmpBadrecord(empBadrecord); this.empBadRecordService.createEmpBadRecord(empBadrecord); } catch (Exception e) { String message = "新增EmpBadrecord失败"; log.error(message, e); @@ -58,25 +64,24 @@ } } @DeleteMapping @DeleteMapping("{ids}") @PreAuthorize("hasAuthority('empBadrecord:delete')") public void deleteEmpBadrecord(EmpBadRecord empBadrecord) throws FebsException { public void logicDeleteEmpBadRecord(@PathVariable("ids") String ids) throws FebsException { try { this.empBadrecordService.deleteEmpBadRecord(empBadrecord); this.empBadRecordService.logicDelEmpBadRecord(ids); } catch (Exception e) { String message = "删除EmpBadrecord失败"; String message = "逻辑删除员工不良记录失败"; log.error(message, e); throw new FebsException(message); } } @PutMapping @PreAuthorize("hasAuthority('empBadrecord:update')") public void updateEmpBadrecord(EmpBadRecord empBadrecord) throws FebsException { public void updateEmpBadRecord(EmpBadRecord empBadrecord) throws FebsException { try { this.empBadrecordService.updateEmpBadrecord(empBadrecord); this.empBadRecordService.updateEmpBadRecord(empBadrecord); } catch (Exception e) { String message = "修改EmpBadrecord失败"; String message = "修改员工不良记录失败"; log.error(message, e); throw new FebsException(message); } febs-server/febs-server-hr/src/main/java/cc/mrbird/febs/server/hr/entity/EmpBadRecord.java
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.Version; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Data; @@ -97,6 +98,7 @@ /** * 记录版本号,用来进行乐观锁控制 */ @Version @TableField("version") private Integer version; febs-server/febs-server-hr/src/main/java/cc/mrbird/febs/server/hr/mapper/EmpBadRecordMapper.java
@@ -2,17 +2,30 @@ import cc.mrbird.febs.server.hr.entity.EmpBadRecord; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; import java.util.List; /** * * name:EmpBadrecord * package:cc.mrbird.febs.server.hr.controller * description:员工不良记录信息实体Mapper * * @author luoyibo * @date 2021-01-24 20:35:55 * @since JDK1.8 */ * name:EmpBadrecord * package:cc.mrbird.febs.server.hr.controller * description:员工不良记录信息实体Mapper * * @author luoyibo * @date 2021-01-24 20:35:55 * @since JDK1.8 */ public interface EmpBadRecordMapper extends BaseMapper<EmpBadRecord> { @Update("<script> " + " UPDATE t_emp_badrecord SET delFlag = 1,\n" + " modifyTime = NOW(),\n" + " modifier = #{operatorId}, \n" + " version = version+1 \n" + " WHERE badId IN \n" + " <foreach item=\"delId\" collection=\"list\" open=\"(\" close=\")\" separator=\",\">\n" + " #{delId}\n" + " </foreach>\n" + "</script>") void logicDeleteByIds(@Param("list") List<String> list,@Param("operatorId") String operatorId); } febs-server/febs-server-hr/src/main/java/cc/mrbird/febs/server/hr/service/IEmpBadRecordService.java
@@ -26,7 +26,7 @@ * @param empBadrecord empBadrecord * @return IPage<EmpBadrecord> */ IPage<EmpBadRecord> findEmpBadrecords(QueryRequest request, EmpBadRecord empBadrecord); IPage<EmpBadRecord> findEmpBadRecords(QueryRequest request, EmpBadRecord empBadrecord); /** * 查询(所有) @@ -34,21 +34,21 @@ * @param empBadrecord empBadrecord * @return List<EmpBadrecord> */ List<EmpBadRecord> findEmpBadrecords(EmpBadRecord empBadrecord); List<EmpBadRecord> findEmpBadRecords(EmpBadRecord empBadrecord); /** * 新增 * * @param empBadrecord empBadrecord */ void createEmpBadrecord(EmpBadRecord empBadrecord); void createEmpBadRecord(EmpBadRecord empBadrecord); /** * 修改 * * @param empBadrecord empBadrecord */ void updateEmpBadrecord(EmpBadRecord empBadrecord); void updateEmpBadRecord(EmpBadRecord empBadrecord); /** * 删除 @@ -56,4 +56,6 @@ * @param empBadrecord empBadrecord */ void deleteEmpBadRecord(EmpBadRecord empBadrecord); void logicDelEmpBadRecord(String ids); } febs-server/febs-server-hr/src/main/java/cc/mrbird/febs/server/hr/service/impl/EmpBadRecordServiceImpl.java
@@ -1,8 +1,12 @@ package cc.mrbird.febs.server.hr.service.impl; import cc.mrbird.febs.common.core.constant.ModuleCode; import cc.mrbird.febs.common.core.utils.FebsUtil; import cc.mrbird.febs.common.core.utils.SequenceUtil; import cc.mrbird.febs.server.hr.entity.EmpBadRecord; import cc.mrbird.febs.server.hr.mapper.EmpBadRecordMapper; import cc.mrbird.febs.server.hr.service.IEmpBadRecordService; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Propagation; @@ -13,58 +17,85 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import cc.mrbird.febs.common.core.entity.QueryRequest; import java.util.List; import java.util.*; /** * * name:EmpBadrecord * package:cc.mrbird.febs.server.hr.controller * description:员工不良记录信息服务接口实现 * * @author luoyibo * @date 2021-01-24 20:35:55 * @since JDK1.8 */ * name:EmpBadrecord * package:cc.mrbird.febs.server.hr.controller * description:员工不良记录信息服务接口实现 * * @author luoyibo * @date 2021-01-24 20:35:55 * @since JDK1.8 */ @Service @RequiredArgsConstructor @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) public class EmpBadRecordServiceImpl extends ServiceImpl <EmpBadRecordMapper, EmpBadRecord> implements IEmpBadRecordService { <EmpBadRecordMapper, EmpBadRecord> implements IEmpBadRecordService { private final EmpBadRecordMapper empBadrecordMapper; private final EmpBadRecordMapper empBadrecordMapper; private final String operatorId = Optional.ofNullable(FebsUtil.getCurrentUser()) .map(u -> u.getUserId().toString()) .orElse("1"); @Override public IPage<EmpBadRecord> findEmpBadrecords(QueryRequest request, EmpBadRecord empBadrecord) { LambdaQueryWrapper<EmpBadRecord> queryWrapper = new LambdaQueryWrapper<>(); // TODO 设置查询条件 Page<EmpBadRecord> page = new Page<>(request.getPageNum(), request.getPageSize()); return this.page(page, queryWrapper); } @Override public IPage<EmpBadRecord> findEmpBadRecords(QueryRequest request, EmpBadRecord empBadrecord) { LambdaQueryWrapper<EmpBadRecord> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(EmpBadRecord::getDelFlag, 0); @Override public List<EmpBadRecord> findEmpBadrecords(EmpBadRecord empBadrecord) { LambdaQueryWrapper<EmpBadRecord> queryWrapper = new LambdaQueryWrapper<>(); // TODO 设置查询条件 return this.baseMapper.selectList(queryWrapper); } Page<EmpBadRecord> page = new Page<>(request.getPageNum(), request.getPageSize()); return this.page(page, queryWrapper); } @Override @Transactional(rollbackFor = Exception.class) public void createEmpBadrecord(EmpBadRecord empBadrecord) { this.save(empBadrecord); } @Override public List<EmpBadRecord> findEmpBadRecords(EmpBadRecord empBadrecord) { LambdaQueryWrapper<EmpBadRecord> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(EmpBadRecord::getDelFlag, 0); @Override @Transactional(rollbackFor = Exception.class) public void updateEmpBadrecord(EmpBadRecord empBadrecord) { this.saveOrUpdate(empBadrecord); } return this.baseMapper.selectList(queryWrapper); } @Override @Transactional(rollbackFor = Exception.class) public void deleteEmpBadRecord(EmpBadRecord empBadrecord) { LambdaQueryWrapper<EmpBadRecord> wapper = new LambdaQueryWrapper<>(); // TODO 设置删除条件 this.remove(wapper); } @Override @Transactional(rollbackFor = Exception.class) public void createEmpBadRecord(EmpBadRecord empBadrecord) { empBadrecord.setBadId(SequenceUtil.generateId(0L, ModuleCode.HR_EMPLOYEE)); empBadrecord.setCreator(operatorId); empBadrecord.setModifier(operatorId); this.save(empBadrecord); } @Override @Transactional(rollbackFor = Exception.class) public void updateEmpBadRecord(EmpBadRecord empBadrecord) { EmpBadRecord dbData = this.getById(empBadrecord.getBadId()); empBadrecord.setCreateTime(dbData.getCreateTime()); empBadrecord.setCreator(dbData.getCreator()); empBadrecord.setDelFlag(dbData.getDelFlag()); empBadrecord.setModifyTime(new Date()); empBadrecord.setModifier(operatorId); this.saveOrUpdate(empBadrecord); } @Override @Transactional(rollbackFor = Exception.class) public void deleteEmpBadRecord(EmpBadRecord empBadrecord) { UpdateWrapper<EmpBadRecord> updateWrapper = new UpdateWrapper<>(); updateWrapper.set("delFlag", 1); updateWrapper.set("modifyTime", new Date()); updateWrapper.set("modifier", operatorId); updateWrapper.set("version", empBadrecord.getVersion() + 1); updateWrapper.eq("badId", empBadrecord.getBadId()); this.update(updateWrapper); } @Override public void logicDelEmpBadRecord(String ids) { List<String> list = new ArrayList<>(); String[] str = ids.split(","); list.addAll(Arrays.asList(str)); empBadrecordMapper.logicDeleteByIds(list, operatorId); } }