|
|
@@ -0,0 +1,273 @@
|
|
|
+package cn.tr.module.smart.common.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.tr.core.exception.TRExcCode;
|
|
|
+import cn.tr.core.strategy.LoginUserStrategy;
|
|
|
+import cn.tr.core.utils.ValidationUtils;
|
|
|
+import cn.tr.module.smart.common.controller.vo.BizReasearchQueueVO;
|
|
|
+import cn.tr.module.smart.common.entity.BizReasearchPushPointEntity;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import cn.tr.core.exception.ServiceException;
|
|
|
+import cn.tr.module.smart.common.repository.BizReasearchQueueRepository;
|
|
|
+import cn.tr.module.smart.common.po.BizReasearchQueuePO;
|
|
|
+import cn.tr.module.smart.common.dto.BizReasearchQueueDTO;
|
|
|
+import cn.tr.module.smart.common.dto.BizReasearchQueueQueryDTO;
|
|
|
+import java.util.*;
|
|
|
+import cn.tr.module.smart.common.service.IBizReasearchQueueService;
|
|
|
+import cn.tr.module.smart.common.mapper.BizReasearchQueueMapper;
|
|
|
+/**
|
|
|
+ * 研究队列Service接口实现类
|
|
|
+ *
|
|
|
+ * @author lf
|
|
|
+ * @date 2025/10/14 17:18
|
|
|
+ **/
|
|
|
+@Service
|
|
|
+public class BizReasearchQueueServiceImpl implements IBizReasearchQueueService {
|
|
|
+ @Autowired
|
|
|
+ private BizReasearchQueueRepository baseRepository;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件查询研究队列
|
|
|
+ * @param query 查询参数
|
|
|
+ * @author lf
|
|
|
+ * @date 2025/10/14 17:18
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<BizReasearchQueueVO> stdSelectBizReasearchQueueList(BizReasearchQueueQueryDTO query){
|
|
|
+ return baseRepository.stdSelectBizReasearchQueueList(query);
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据id查询研究队列
|
|
|
+ * @param id 主键id
|
|
|
+ * @author lf
|
|
|
+ * @date 2025/10/14 17:18
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public BizReasearchQueueVO selectBizReasearchQueueById(String id){
|
|
|
+ return null;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 编辑研究队列
|
|
|
+ * @param source 编辑实体类
|
|
|
+ * @author lf
|
|
|
+ * @date 2025/10/14 17:18
|
|
|
+ */
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ @Override
|
|
|
+ public boolean updateBizReasearchQueueById(BizReasearchQueueDTO source){
|
|
|
+ validateSource(source);
|
|
|
+ BizReasearchQueuePO oldSource = baseRepository.selectById(source.getId());
|
|
|
+ String currentUserId = LoginUserStrategy.tr.getCurrentUserId();
|
|
|
+ if(StrUtil.equals(oldSource.getOwner(),currentUserId)){
|
|
|
+ throw new ServiceException(TRExcCode.SYSTEM_ERROR_B0001,"您没有权限修改该数据");
|
|
|
+ }
|
|
|
+ BizReasearchQueuePO updateSource = BizReasearchQueueMapper.INSTANCE.convertPO(source);
|
|
|
+ updateSource.setTimePointsShow(formatTimePoints(updateSource.getTimePoints()));
|
|
|
+ updateSource.setTimePointsFormat(calculateAndSetTimePointsFormat(updateSource.getTimePoints()));
|
|
|
+ return baseRepository.updateById(updateSource)!=0;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增研究队列
|
|
|
+ * @param source 新增实体类
|
|
|
+ * @author lf
|
|
|
+ * @date 2025/10/14 17:18
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean insertBizReasearchQueue(BizReasearchQueueDTO source){
|
|
|
+ validateSource(source);
|
|
|
+ BizReasearchQueuePO insertSource = BizReasearchQueueMapper.INSTANCE.convertPO(source);
|
|
|
+ insertSource.setOwner(LoginUserStrategy.tr.getCurrentUserId());
|
|
|
+ insertSource.setClinicCount(0);
|
|
|
+ insertSource.setTimePointsShow(formatTimePoints(insertSource.getTimePoints()));
|
|
|
+ insertSource.setTimePointsFormat(calculateAndSetTimePointsFormat(insertSource.getTimePoints()));
|
|
|
+ return baseRepository.insert(insertSource)!=0;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除研究队列详情
|
|
|
+ * @param ids 删除主键集合
|
|
|
+ * @author lf
|
|
|
+ * @date 2025/10/14 17:18
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public int removeBizReasearchQueueByIds(Collection<String> ids){
|
|
|
+ if(CollectionUtil.isEmpty(ids)){
|
|
|
+ throw new ServiceException(TRExcCode.SYSTEM_ERROR_B0001,"请选择要删除的数据");
|
|
|
+ }
|
|
|
+ String currentUserId = LoginUserStrategy.tr.getCurrentUserId();
|
|
|
+ return baseRepository.delete(new LambdaQueryWrapper<BizReasearchQueuePO>()
|
|
|
+ .in(BizReasearchQueuePO::getId,ids)
|
|
|
+ .eq(BizReasearchQueuePO::getOwner,currentUserId));
|
|
|
+ };
|
|
|
+
|
|
|
+ private void validateSource(BizReasearchQueueDTO source){
|
|
|
+ ValidationUtils.validate(source.getTimePoints());
|
|
|
+ for (BizReasearchPushPointEntity timePoint : source.getTimePoints()) {
|
|
|
+ if (!isValidTimePointFormat(timePoint.getTimePoint())) {
|
|
|
+ throw new ServiceException(TRExcCode.SYSTEM_ERROR_B0001,"时间点格式错误");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将推送时间点列表转换为可读的字符串格式
|
|
|
+ * 根据图片中的格式:术后一天、三天、一周、三周、一月
|
|
|
+ *
|
|
|
+ * @param timePoints 推送时间点列表
|
|
|
+ * @return 格式化后的字符串
|
|
|
+ */
|
|
|
+ public String formatTimePoints(List<BizReasearchPushPointEntity> timePoints) {
|
|
|
+ if (timePoints == null || timePoints.isEmpty()) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> formattedPoints = new ArrayList<>();
|
|
|
+
|
|
|
+ for (BizReasearchPushPointEntity point : timePoints) {
|
|
|
+ String timeUnit = point.getTimeUnit();
|
|
|
+ Integer interval = point.getInterval();
|
|
|
+
|
|
|
+ if (interval != null && timeUnit != null) {
|
|
|
+ String formattedPoint = formatSingleTimePoint(interval, timeUnit);
|
|
|
+ formattedPoints.add(formattedPoint);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按照时间间隔从小到大排序(先按单位,再按数值)
|
|
|
+ formattedPoints.sort((a, b) -> {
|
|
|
+ // 提取数字和单位
|
|
|
+ String[] aParts = a.split("(?<=\\d)(?=\\D)");
|
|
|
+ String[] bParts = b.split("(?<=\\d)(?=\\D)");
|
|
|
+
|
|
|
+ int aNum = Integer.parseInt(aParts[0].replaceAll("术后", ""));
|
|
|
+ String aUnit = aParts[1];
|
|
|
+
|
|
|
+ int bNum = Integer.parseInt(bParts[0].replaceAll("术后", ""));
|
|
|
+ String bUnit = bParts[1];
|
|
|
+
|
|
|
+ // 先比较单位(day < week < month < year),再比较数值
|
|
|
+ int unitCompare = compareUnits(aUnit, bUnit);
|
|
|
+ if (unitCompare != 0) {
|
|
|
+ return unitCompare;
|
|
|
+ }
|
|
|
+ return Integer.compare(aNum, bNum);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 使用顿号连接所有时间点
|
|
|
+ return String.join("、", formattedPoints);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 比较时间单位的顺序
|
|
|
+ * @param unit1 第一个单位
|
|
|
+ * @param unit2 第二个单位
|
|
|
+ * @return 比较结果
|
|
|
+ */
|
|
|
+ private int compareUnits(String unit1, String unit2) {
|
|
|
+ Map<String, Integer> unitOrder = new HashMap<>();
|
|
|
+ unitOrder.put("天", 1);
|
|
|
+ unitOrder.put("周", 2);
|
|
|
+ unitOrder.put("月", 3);
|
|
|
+ unitOrder.put("年", 4);
|
|
|
+
|
|
|
+ return Integer.compare(unitOrder.getOrDefault(unit1, 5), unitOrder.getOrDefault(unit2, 5));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 格式化单个时间点为可读字符串
|
|
|
+ *
|
|
|
+ * @param interval 时间间隔
|
|
|
+ * @param timeUnit 时间单位
|
|
|
+ * @return 格式化后的字符串
|
|
|
+ */
|
|
|
+ private String formatSingleTimePoint(Integer interval, String timeUnit) {
|
|
|
+ switch (timeUnit) {
|
|
|
+ case "day":
|
|
|
+ return "术后" + interval + "天";
|
|
|
+ case "week":
|
|
|
+ return "术后" + interval + "周";
|
|
|
+ case "month":
|
|
|
+ return "术后" + interval + "月";
|
|
|
+ case "year":
|
|
|
+ return "术后" + interval + "年";
|
|
|
+ default:
|
|
|
+ return "术后" + interval + "天"; // 默认按天计算
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算并设置推送时间点间隔(按从小到大排序)
|
|
|
+ * @param timePoints 推送时间点列表
|
|
|
+ */
|
|
|
+ public List<Long> calculateAndSetTimePointsFormat(List<BizReasearchPushPointEntity> timePoints) {
|
|
|
+ List<Long> result=new ArrayList<>();
|
|
|
+ if (timePoints == null || timePoints.isEmpty()) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ List<Long> intervals = new ArrayList<>();
|
|
|
+
|
|
|
+ for (BizReasearchPushPointEntity pushPoint : timePoints) {
|
|
|
+ String timeUnit = pushPoint.getTimeUnit();
|
|
|
+ Integer interval = pushPoint.getInterval();
|
|
|
+
|
|
|
+ if (interval != null) {
|
|
|
+ long milliseconds = convertToMilliseconds(interval, timeUnit);
|
|
|
+ intervals.add(milliseconds);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按间隔从小到大排序
|
|
|
+ intervals.sort(Long::compareTo);
|
|
|
+ return intervals;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将时间间隔转换为毫秒数
|
|
|
+ * @param interval 时间间隔
|
|
|
+ * @param timeUnit 时间单位
|
|
|
+ * @return 毫秒数
|
|
|
+ */
|
|
|
+ private long convertToMilliseconds(Integer interval, String timeUnit) {
|
|
|
+ switch (timeUnit) {
|
|
|
+ case "day":
|
|
|
+ return interval * 24L * 60 * 60 * 1000;
|
|
|
+ case "week":
|
|
|
+ return interval * 7L * 24 * 60 * 60 * 1000;
|
|
|
+ case "month":
|
|
|
+ return interval * 30L * 24 * 60 * 60 * 1000; // 近似值
|
|
|
+ case "year":
|
|
|
+ return interval * 365L * 24 * 60 * 60 * 1000; // 近似值
|
|
|
+ default:
|
|
|
+ return interval * 60L * 1000; // 默认按分钟计算
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验时间点格式是否为HH:mm格式
|
|
|
+ * @param timePoint 时间点字符串
|
|
|
+ * @return 是否符合HH:mm格式
|
|
|
+ */
|
|
|
+ public boolean isValidTimePointFormat(String timePoint) {
|
|
|
+ if (timePoint == null || timePoint.isEmpty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 正则表达式匹配HH:mm格式
|
|
|
+ // 支持00:00到23:59的时间格式
|
|
|
+ String timePattern = "^([01]?[0-9]|2[0-3]):[0-5][0-9]$";
|
|
|
+ return timePoint.matches(timePattern);
|
|
|
+ }
|
|
|
+}
|