From ced81f823e56b2c46c283b3564567c1f10221d12 Mon Sep 17 00:00:00 2001 From: Zhuangxingyu Date: Mon, 24 Feb 2025 13:31:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4=20?= =?UTF-8?q?=E9=87=87=E7=95=AA=E7=BB=84=E4=BB=B6=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/common/constant/CacheConstants.java | 5 + .../core/common/core/redis/RedisCache.java | 16 ++ .../com/core/common/enums/AssignSeqEnum.java | 42 +++ .../com/core/common/utils/AssignSeqUtil.java | 267 ++++++++++++++++++ .../java/com/core/common/utils/DateUtils.java | 23 ++ .../controller/ItemDefinitionController.java | 53 ++++ 6 files changed, 406 insertions(+) create mode 100644 openhis-server/core-common/src/main/java/com/core/common/enums/AssignSeqEnum.java create mode 100644 openhis-server/core-common/src/main/java/com/core/common/utils/AssignSeqUtil.java diff --git a/openhis-server/core-common/src/main/java/com/core/common/constant/CacheConstants.java b/openhis-server/core-common/src/main/java/com/core/common/constant/CacheConstants.java index 4985100e..16424fcf 100644 --- a/openhis-server/core-common/src/main/java/com/core/common/constant/CacheConstants.java +++ b/openhis-server/core-common/src/main/java/com/core/common/constant/CacheConstants.java @@ -40,4 +40,9 @@ public class CacheConstants { * 登录账户密码错误次数 redis key */ public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; + + /** + * 超出上限,排番失败(时间:{},KEY:{} + */ + public static final String ASSIGN_SEQ_FAILED = "排番失败(时间:{},KEY:{},异常信息:{超出上限})"; } diff --git a/openhis-server/core-common/src/main/java/com/core/common/core/redis/RedisCache.java b/openhis-server/core-common/src/main/java/com/core/common/core/redis/RedisCache.java index 36e7d8b7..9522f9cf 100644 --- a/openhis-server/core-common/src/main/java/com/core/common/core/redis/RedisCache.java +++ b/openhis-server/core-common/src/main/java/com/core/common/core/redis/RedisCache.java @@ -3,6 +3,7 @@ package com.core.common.core.redis; import java.util.*; import java.util.concurrent.TimeUnit; +import com.core.common.exception.UtilException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.BoundSetOperations; import org.springframework.data.redis.core.HashOperations; @@ -240,4 +241,19 @@ public class RedisCache { public Collection keys(final String pattern) { return redisTemplate.keys(pattern); } + + /** + * 递增 + * + * @param key 缓存Key + * @param delta 要增加的幅度(大于0) + * @return 递增后的值 + */ + public long incr(String key, long delta) { + if (delta < 0L) { + throw new UtilException("递增因子必须大于0"); + } else { + return this.redisTemplate.opsForValue().increment(key, delta); + } + } } diff --git a/openhis-server/core-common/src/main/java/com/core/common/enums/AssignSeqEnum.java b/openhis-server/core-common/src/main/java/com/core/common/enums/AssignSeqEnum.java new file mode 100644 index 00000000..188b305a --- /dev/null +++ b/openhis-server/core-common/src/main/java/com/core/common/enums/AssignSeqEnum.java @@ -0,0 +1,42 @@ +/* + * Copyright ©2023 CJB-CNIT Team. All rights reserved + */ +package com.core.common.enums; + +import com.core.common.utils.StringUtils; + +/** + * 采番前缀枚举 + * + * @author zxy + * @date 2025-02-24 + */ +public enum AssignSeqEnum { + + /** + * 例子 + */ + TEST("1", "例子", "TE"); + + private final String code; + private final String info; + private final String prefix; + + AssignSeqEnum(String code, String info, String prefix) { + this.code = code; + this.info = info; + this.prefix = prefix; + } + + public String getCode() { + return code; + } + + public String getInfo() { + return info; + } + + public String getPrefix() { + return prefix; + } +} \ No newline at end of file diff --git a/openhis-server/core-common/src/main/java/com/core/common/utils/AssignSeqUtil.java b/openhis-server/core-common/src/main/java/com/core/common/utils/AssignSeqUtil.java new file mode 100644 index 00000000..3706d5ce --- /dev/null +++ b/openhis-server/core-common/src/main/java/com/core/common/utils/AssignSeqUtil.java @@ -0,0 +1,267 @@ +/* + * Copyright ©2023 CJB-CNIT Team. All rights reserved + */ +package com.core.common.utils; + +import java.util.ArrayList; +import java.util.List; + +import com.core.common.constant.CacheConstants; +import com.core.common.core.redis.RedisCache; +import com.core.common.exception.UtilException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * 排番组件 + * + * @author zxy + * @date 2024-11-29 + */ +@Component +public final class AssignSeqUtil { + private final RedisCache redisCache; + + // 缓存Key格式(包含前缀) + private static final String FORMAT_CACHE_KEY = "assign-seq:%s"; + + // 缓存Key格式(包含前缀) + private static final String FORMAT_CACHE_KEY_BY_DAY = "assign-seq:%s:%s"; + + // 默认序号长度 + private static final int DEFAULT_SUFFIX_LENGTH = 8; + + // 默认序号长度(每日重新排番) + private static final int DEFAULT_SUFFIX_LENGTH_DAY = 4; + + // 编号格式前缀 + private static final String FORMAT_SEQ_PREFIX = "%s%0"; + + // 编号格式前缀 + private static final String FORMAT_SEQ_PREFIX_DAY = "%s%s%0"; + + // 编号格式后缀 + private static final String FORMAT_SEQ_SUFFIX = "d"; + + // 失效时长(48小时) + private static final int EXPIRE_SECONDS = 172800; + + private AssignSeqUtil(RedisCache redisCache) { + this.redisCache = redisCache; + } + + private static final Logger log = LoggerFactory.getLogger(AssignSeqUtil.class); + + /** + * 编号排番 + * + * @param prefix 编号前缀 + * @return 番号(示例:XXX00000001) + */ + public String getSeq(String prefix) { + return this.getSeq(prefix, DEFAULT_SUFFIX_LENGTH); + } + + /** + * 编号排番 + * + * @param prefix 编号前缀 + * @param seqLength 序号长度(去除前缀后位数) + * @return 番号(示例:XXX00000001) + */ + public String getSeq(String prefix, int seqLength) { + return String.format(FORMAT_SEQ_PREFIX + seqLength + FORMAT_SEQ_SUFFIX, prefix, this.getSeqNo(prefix)); + } + + /** + * 编号排番(批量) + * + * @param prefix 编号前缀 + * @param seqLength 序号长度(去除前缀后位数) + * @param count 排番数量 + * @return 番号(示例:XXX00000001,XXX00000002) + */ + public List getSeq(String prefix, int seqLength, int count) { + + // 获取最新编号 + int seqEnd = this.getSeqNoCore(String.format(FORMAT_CACHE_KEY, prefix), count); + + // 返回番号集合 + List seqS = new ArrayList<>(); + long seq = seqEnd - count + 1; + while (seq <= seqEnd) { + // 拼接番号 + seqS.add(String.format(FORMAT_SEQ_PREFIX + seqLength + FORMAT_SEQ_SUFFIX, prefix, seq++)); + } + return seqS; + } + + /** + * 编号排番 + * + * @param key 编号主键 + * @return 番号(示例:XXX00000001) + */ + public int getSeqNo(String key) { + return this.getSeqNoCore(String.format(FORMAT_CACHE_KEY, key), 1); + } + + /** + * 编号排番(批量) + * + * @param key 编号主键 + * @param count 排番数量 + * @return 番号(示例:XXX00000001,XXX00000002) + */ + public List getSeqNo(String key, int count) { + + // 获取最新编号 + int seqEnd = this.getSeqNoCore(String.format(FORMAT_CACHE_KEY, key), count); + + // 返回番号集合 + List seqS = new ArrayList<>(); + int seq = seqEnd - count + 1; + while (seq <= seqEnd) { + // 拼接番号 + seqS.add(seq++); + } + return seqS; + } + + /** + * 编号排番(每日重新排番) + * + * @param prefix 编号前缀 + * @return 番号 + */ + public String getSeqByDay(String prefix) { + return this.getSeqByDay(prefix, DEFAULT_SUFFIX_LENGTH_DAY); + } + + /** + * 编号排番(每日重新排番) + * + * @param prefix 编号前缀 + * @param seqLength 序号长度(去除前缀后位数) + * @return 番号 + */ + public String getSeqByDay(String prefix, int seqLength) { + // 获取当前日期 + String today = DateUtils.today(); + + // 获取最新编号 + int seq = this.getSeqNoByDay(prefix, today, 1); + + // 拼接番号并返回 + return String.format(FORMAT_SEQ_PREFIX_DAY + seqLength + FORMAT_SEQ_SUFFIX, prefix, today, seq); + } + + /** + * 编号排番(每日重新排番)(批量) + * + * @param prefix 编号前缀 + * @param seqLength 序号长度(去除前缀后位数) + * @param count 排番数量 + * @return 番号(最小值) + */ + public List getSeqByDay(String prefix, int seqLength, int count) { + + // 获取当前日期 + String today = DateUtils.today(); + + // 获取最新编号 + int seqEnd = this.getSeqNoByDay(prefix, today, count); + + // 返回番号集合 + List seqS = new ArrayList<>(); + long seq = seqEnd - count + 1; + while (seq <= seqEnd) { + // 拼接番号 + seqS.add(String.format(FORMAT_SEQ_PREFIX_DAY + seqLength + FORMAT_SEQ_SUFFIX, prefix, today, seq++)); + } + return seqS; + } + + /** + * 编号排番(每日重新排番) + * + * @param prefix 编号前缀 + * @return 番号 + */ + public int getSeqNoByDay(String prefix) { + return this.getSeqNoByDay(prefix, DateUtils.today(), 1); + } + + /** + * 编号排番(每日重新排番)(批量) + * + * @param prefix 编号前缀 + * @param count 排番数量 + * @return 番号(最小值) + */ + public List getSeqNoByDay(String prefix, int count) { + + // 获取当前日期 + String today = DateUtils.today(); + + // 获取最新编号 + int seqEnd = this.getSeqNoByDay(prefix, today, count); + + // 返回番号集合 + List seqS = new ArrayList<>(); + int seq = seqEnd - count + 1; + while (seq <= seqEnd) { + // 拼接番号 + seqS.add(seq++); + } + return seqS; + } + + /** + * 编号排番(每日重新排番) + * + * @param prefix 编号前缀 + * @param date 序号长度(去除前缀后位数) + * @param count 排番数量 + * @return 番号 + */ + private int getSeqNoByDay(String prefix, String date, int count) { + + // 拼接缓存Key(包含当日日期) + String cacheKeyByDay = String.format(FORMAT_CACHE_KEY_BY_DAY, prefix, date); + + // 获取最新编号 + int seq = this.getSeqNoCore(cacheKeyByDay, count); + + // 当最小编号为1时,设置保存期限 + if (seq - count + 1 == 1) { + redisCache.expire(cacheKeyByDay, EXPIRE_SECONDS); + } + + // 拼接番号并返回 + return seq; + } + + /** + * 编号排番(批量) + * + * @param cacheKey 缓存Key + * @param count 排番数量 + * @return 番号(示例:XXX00000001,XXX00000002) + */ + private int getSeqNoCore(String cacheKey, int count) { + + // 获取最新编号 + long seq = redisCache.incr(cacheKey, count); + + // 达到最大值时重置番号 + if (seq >= Integer.MAX_VALUE) { + log.error(CacheConstants.ASSIGN_SEQ_FAILED, DateUtils.getStrYmdHmsRead(), cacheKey); + throw new UtilException("排番失败!"); + } + + // 番号返回 + return (int)seq; + } +} diff --git a/openhis-server/core-common/src/main/java/com/core/common/utils/DateUtils.java b/openhis-server/core-common/src/main/java/com/core/common/utils/DateUtils.java index 37fa6f22..691b21ce 100644 --- a/openhis-server/core-common/src/main/java/com/core/common/utils/DateUtils.java +++ b/openhis-server/core-common/src/main/java/com/core/common/utils/DateUtils.java @@ -22,8 +22,12 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + public static String YYYYMMDD = "yyyyMMdd"; + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + public static String YMDHMS_FOR_READ = "yyyy年MM月dd日 HH时mm分ss秒"; + private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; @@ -90,6 +94,25 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { return DateFormatUtils.format(now, "yyyyMMdd"); } + /** + * 获取当日日期 + * + * @return 当日日期 + */ + public static final String today() + { + return dateTimeNow(YYYYMMDD); + } + + /** + * 获取当日日期(可读) + * @return + */ + public static final String getStrYmdHmsRead() + { + return dateTimeNow(YMDHMS_FOR_READ); + } + /** * 日期型字符串转化为日期 格式 */ diff --git a/openhis-server/openhis-application/src/main/java/com/openhis/web/datadictionary/controller/ItemDefinitionController.java b/openhis-server/openhis-application/src/main/java/com/openhis/web/datadictionary/controller/ItemDefinitionController.java index efe91db8..13c1469c 100644 --- a/openhis-server/openhis-application/src/main/java/com/openhis/web/datadictionary/controller/ItemDefinitionController.java +++ b/openhis-server/openhis-application/src/main/java/com/openhis/web/datadictionary/controller/ItemDefinitionController.java @@ -4,10 +4,14 @@ package com.openhis.web.datadictionary.controller; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.servlet.http.HttpServletRequest; +import com.core.common.enums.AssignSeqEnum; +import com.core.common.utils.AssignSeqUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -53,6 +57,8 @@ public class ItemDefinitionController { // private IDeviceDefinitionService deviceDefinitionService; // @Autowired(required = false) // private IActivityDefinitionService activityDefinitionService; + @Autowired(required = false) + private AssignSeqUtil assignSeqUtil; /** * 项目定价列表 @@ -127,8 +133,10 @@ public class ItemDefinitionController { } // 通过 DefinitionType 区分药品定价/器具定价/手术定价 if (DefinitionTypeEnum.MEDICATION.getCode().equals(itemDefSearchParam.getDefinitionType())) { + //获取定价列表 chargeItemDefinitionList = chargeItemDefSearchMapper.getMedList(itemDefSearchParam, pageNo, pageSize, skipCount); + //设置分页条件 chargeItemDefinitionPage.setSize(pageSize); chargeItemDefinitionPage.setCurrent(pageNo); if (chargeItemDefinitionList.size() > 0) { @@ -141,8 +149,10 @@ public class ItemDefinitionController { return R.ok(chargeItemDefinitionPage, MessageUtils.createMessage(PromptMsgConstant.Common.M00009, null)); } else if (DefinitionTypeEnum.DEVICE.getCode().equals(itemDefSearchParam.getDefinitionType())) { + //获取定价列表 chargeItemDefinitionList = chargeItemDefSearchMapper.getDevList(itemDefSearchParam, pageNo, pageSize, skipCount); + //设置分页条件 chargeItemDefinitionPage.setSize(pageSize); chargeItemDefinitionPage.setCurrent(pageNo); if (chargeItemDefinitionList.size() > 0) { @@ -155,8 +165,10 @@ public class ItemDefinitionController { return R.ok(chargeItemDefinitionPage, MessageUtils.createMessage(PromptMsgConstant.Common.M00009, null)); } else if (DefinitionTypeEnum.ACTIVITY.getCode().equals(itemDefSearchParam.getDefinitionType())) { + //获取定价列表 chargeItemDefinitionList = chargeItemDefSearchMapper.getActList(itemDefSearchParam, pageNo, pageSize, skipCount); + //设置分页条件 chargeItemDefinitionPage.setSize(pageSize); chargeItemDefinitionPage.setCurrent(pageNo); if (chargeItemDefinitionList.size() > 0) { @@ -197,4 +209,45 @@ public class ItemDefinitionController { ? R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[] {"费用定价"})) : R.fail(PromptMsgConstant.Common.M00007, null); } + + /** + * 采番测试(例子,非常规代码,请勿调用) + * + * @return 采番测试结果 + */ + @GetMapping(value = "/test-assign") + public R getTestAssign() { + // 基础采番 + String code = assignSeqUtil.getSeq(AssignSeqEnum.TEST.getPrefix()); + // 控制长度采番(seqLength: 总长度) + String code1 = assignSeqUtil.getSeq(AssignSeqEnum.TEST.getPrefix(),8); + // 控制长度批量采番 + List code2 = assignSeqUtil.getSeq(AssignSeqEnum.TEST.getPrefix(),8,3); + // 获取编号 + Integer code3 = assignSeqUtil.getSeqNo(AssignSeqEnum.TEST.getPrefix()); + // 批量获取编号 + List code4 = assignSeqUtil.getSeqNo(AssignSeqEnum.TEST.getPrefix(),3); + // 每日采番 + String code5 = assignSeqUtil.getSeqByDay(AssignSeqEnum.TEST.getPrefix()); + // 每日按长度采番(seqLength: 日期后的数字位数) + String code6 = assignSeqUtil.getSeqByDay(AssignSeqEnum.TEST.getPrefix(),8); + // 每日批量采番 + List code7 = assignSeqUtil.getSeqByDay(AssignSeqEnum.TEST.getPrefix(),8,3); + // 每日获取编号 + Integer code8 = assignSeqUtil.getSeqNoByDay(AssignSeqEnum.TEST.getPrefix()); + // 每日批量获取编号 + List code9 = assignSeqUtil.getSeqNoByDay(AssignSeqEnum.TEST.getPrefix(),3); + Map map = new HashMap<>(); + map.put("code",code); + map.put("code1",code1); + map.put("code2",code2); + map.put("code3",code3); + map.put("code4",code4); + map.put("code5",code5); + map.put("code6",code6); + map.put("code7",code7); + map.put("code8",code8); + map.put("code9",code9); + return R.ok(map); + } }