护理单元同步

This commit is contained in:
1378012178@qq.com 2025-06-25 09:03:38 +08:00
parent 847fca16b3
commit 25aa026fcd
14 changed files with 348 additions and 81 deletions

View File

@ -0,0 +1,12 @@
package com.nu.modules.nubaseinfo.api;
import com.nu.modules.nubaseinfo.entity.NuBaseInfoApiDto;
import java.util.List;
public interface INuBaseInfoApi {
public void save(NuBaseInfoApiDto dto);
void sync();
}

View File

@ -0,0 +1,43 @@
package com.nu.modules.nubaseinfo.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @Description: 护理单元
* @Author: jeecg-boot
* @Date: 2025-04-11
* @Version: V1.0
*/
@Data
public class NuBaseInfoApiDto implements Serializable {
private static final long serialVersionUID = 1L;
/**ID*/
private String id;
/**护理单元名称*/
private String nuName;
/**护理单元编码*/
private String nuId;
/**区域标签ID*/
private String areaFlag;
/**使用状态 0未使用 1占用 2入住 3退住 4留床*/
private String status;
/**客户*/
private String customerId;
/**是否删除 0未删除 1删除*/
private String delFlag;
/**创建人*/
private String createBy;
/**创建日期*/
private java.util.Date createTime;
/**更新人*/
private String updateBy;
/**更新日期*/
private java.util.Date updateTime;
/**所属部门*/
private String sysOrgCode;
private String orgCode;
private String asyncId;
}

View File

@ -1,50 +1,28 @@
package com.nu.modules.nuBaseInfo.controller;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.nu.modules.nuBizAdvisoryInfo.entity.NuBizAdvisoryInfo;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.util.oConvertUtils;
import com.nu.modules.nuBaseInfo.entity.NuBaseInfo;
import com.nu.modules.nuBaseInfo.service.INuBaseInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.commons.util.IdUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.nu.modules.nuBaseInfo.entity.NuBaseInfo;
import com.nu.modules.nuBaseInfo.service.INuBaseInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: 护理单元
@ -59,8 +37,6 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
public class NuBaseInfoController extends JeecgController<NuBaseInfo, INuBaseInfoService> {
@Autowired
private INuBaseInfoService nuBaseInfoService;
@Autowired
private ISysBaseAPI sysBaseAPI;
/**
* 分页列表查询
@ -98,24 +74,7 @@ public class NuBaseInfoController extends JeecgController<NuBaseInfo, INuBaseInf
@RequiresPermissions("nuBaseInfo:nu_base_info:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody NuBaseInfo nuBaseInfo) {
JSONObject deptInfo = sysBaseAPI.getDeptInfo();
String orgCode = deptInfo.getString("code");
if (StringUtils.isBlank(orgCode)) {
throw new RuntimeException("请先在部门管理中设置机构编码!");
}
try {
Integer code = nuBaseInfoService.getCode();
if (code == null) {
nuBaseInfo.setCode(orgCode + "-001");
} else {
//保证3位字符串 不足前面用0补全
String codeStr = String.format("%03d", code + 1);
nuBaseInfo.setCode(orgCode + "-" + codeStr);
}
} catch (Exception e) {
e.printStackTrace();
nuBaseInfo.setCode(orgCode + "-" + IdUtil.simpleUUID());
}
service.setNuId(nuBaseInfo);
nuBaseInfoService.save(nuBaseInfo);
return Result.OK("添加成功!");
}

View File

@ -1,24 +1,20 @@
package com.nu.modules.nuBaseInfo.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
/**
* @Description: 护理单元
@ -45,7 +41,7 @@ public class NuBaseInfo implements Serializable {
/**护理单元编码*/
@Excel(name = "护理单元编码", width = 15)
@ApiModelProperty(value = "护理单元编码")
private java.lang.String code;
private java.lang.String nuId;
/**区域标签ID*/
@Excel(name = "区域标签ID", width = 15, dicCode = "nu_type")
@Dict(dicCode = "nu_type")
@ -84,4 +80,7 @@ public class NuBaseInfo implements Serializable {
/**所属部门*/
@ApiModelProperty(value = "所属部门")
private java.lang.String sysOrgCode;
/**是否已同步0已同步 1未同步*/
@ApiModelProperty(value = "是否已同步0已同步 1未同步")
private java.lang.String izSync;
}

View File

@ -14,6 +14,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface NuBaseInfoMapper extends BaseMapper<NuBaseInfo> {
Integer getCode();
String getNuId();
}

View File

@ -2,9 +2,9 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nu.modules.nuBaseInfo.mapper.NuBaseInfoMapper">
<select id="getCode" resultType="java.lang.Integer">
SELECT MAX(CAST(SUBSTRING_INDEX(code, '-', -1) AS UNSIGNED)) AS max_number
<select id="getNuId" resultType="java.lang.String">
SELECT MAX(nu_id) AS max_number
FROM nu_base_info
WHERE SUBSTRING_INDEX(code, '-', -1) REGEXP '^[0-9]+$';
WHERE RIGHT(nu_id, 3) REGEXP '^[0-9]{3}$'
</select>
</mapper>

View File

@ -1,7 +1,9 @@
package com.nu.modules.nuBaseInfo.service;
import com.nu.modules.nuBaseInfo.entity.NuBaseInfo;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nu.modules.nuBaseInfo.entity.NuBaseInfo;
import java.util.List;
/**
* @Description: 护理单元
@ -11,5 +13,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface INuBaseInfoService extends IService<NuBaseInfo> {
Integer getCode();
void setNuId(NuBaseInfo nuBaseInfo);
List<NuBaseInfo> getSynchronized(String dataSourceCode,String orgCode);
void batchInsert(List<NuBaseInfo> syncList);
}

View File

@ -1,11 +1,23 @@
package com.nu.modules.nuBaseInfo.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nu.modules.nuBaseInfo.entity.NuBaseInfo;
import com.nu.modules.nuBaseInfo.mapper.NuBaseInfoMapper;
import com.nu.modules.nuBaseInfo.service.INuBaseInfoService;
import com.nu.modules.nubaseinfo.api.INuBaseInfoApi;
import com.nu.modules.nubaseinfo.entity.NuBaseInfoApiDto;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* @Description: 护理单元
@ -14,10 +26,72 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
* @Version: V1.0
*/
@Service
public class NuBaseInfoServiceImpl extends ServiceImpl<NuBaseInfoMapper, NuBaseInfo> implements INuBaseInfoService {
public class NuBaseInfoServiceImpl extends ServiceImpl<NuBaseInfoMapper, NuBaseInfo> implements INuBaseInfoService, INuBaseInfoApi {
@Autowired
private ISysBaseAPI sysBaseAPI;
@Override
public Integer getCode() {
return baseMapper.getCode();
public void setNuId(NuBaseInfo nuBaseInfo) {
JSONObject deptInfo = sysBaseAPI.getDeptInfo();
String orgCode = deptInfo.getString("code");
if (StringUtils.isBlank(orgCode)) {
throw new RuntimeException("请先在部门管理中设置机构编码!");
}
try {
String nuId = baseMapper.getNuId();
if (nuId == null) {
// 年月 + 机构编码 + 001
nuBaseInfo.setNuId(LocalDate.now().format(DateTimeFormatter.ofPattern("yyMM")) + orgCode + "001");
} else {
// 取最后3位
String last3Digits = nuId.substring(nuId.length() - 3);
// 转为整数并加1
int nextNum = Integer.parseInt(last3Digits) + 1;
// 格式化为3位数字不足补零
String formattedNum = String.format("%03d", nextNum);
// 设置新的nuId
nuBaseInfo.setNuId(LocalDate.now().format(DateTimeFormatter.ofPattern("yyMM")) + orgCode + formattedNum);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("护理单元添加失败,请联系管理员进行处理!");
}
}
@Override
@DS("#dataSourceCode")
public List<NuBaseInfo> getSynchronized(String dataSourceCode,String orgCode) {
QueryWrapper<NuBaseInfo> qw = new QueryWrapper<>();
qw.eq("sys_org_code",orgCode);
qw.eq("iz_sync","1");
qw.eq("del_flag","0");
return baseMapper.selectList(qw);
}
@Override
public void batchInsert(List<NuBaseInfo> syncList) {
syncList.stream().forEach(bi -> {
bi.setIzSync("0");
baseMapper.insert(bi);
});
}
@Override
public void save(NuBaseInfoApiDto dto) {
NuBaseInfo nuBaseInfo = new NuBaseInfo();
BeanUtils.copyProperties(dto,nuBaseInfo);
setNuId(nuBaseInfo);
nuBaseInfo.setSysOrgCode(dto.getOrgCode());
baseMapper.insert(nuBaseInfo);
}
/**
* 同步数据
* 逻辑从运维数据库中查出本机构下iz_sync = 1的数据存到自己的库里 存之前把这个状态改为0
*/
@Override
public void sync() {
}
}

View File

@ -0,0 +1,28 @@
package com.nu.mq.nubaseinfo.exceptionhandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.RabbitListenerErrorHandler;
import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException;
import org.springframework.stereotype.Component;
@Slf4j
@Component("nuBaseInfoMQErrorHandler")
public class NuBaseInfoMQExceptionHandler implements RabbitListenerErrorHandler {
@Override
public Object handleError(Message message, org.springframework.messaging.Message<?> message1, ListenerExecutionFailedException e) {
log.error("MQ消息处理失败 | 消息体: {} | 异常原因: {}", new String(message.getBody()), e.getCause().getMessage());
// 根据异常类型选择处理策略
// if (isRetryable(e)) {
// // 可重试异常抛出异常触发重试
// throw e;
// } else {
// 不可恢复异常拒绝消息且不重新入队
throw new AmqpRejectAndDontRequeueException("消息处理失败且禁止重试", e);
// }
}
}

View File

@ -0,0 +1,28 @@
package com.nu.mq.nubaseinfo.listener;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("hldyAsyncDQNP")
public class DynamicQueueNameProvider {
@Autowired
private ISysBaseAPI sysBaseAPI;
public String getQueueName() {
JSONObject deptInfo = sysBaseAPI.getDeptInfo();
String orgCode = deptInfo.getString("code");
if (StringUtils.isNotBlank(orgCode)) {
return orgCode + ".hldy.async";
} else {
return "";
}
}
public String getKeyName() {
return getQueueName();
}
}

View File

@ -0,0 +1,91 @@
package com.nu.mq.nubaseinfo.listener;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.nu.dto.NuBaseInfoMQDto;
import com.nu.dto.StatusMQDto;
import com.nu.enums.MQStatus;
import com.nu.modules.nuBaseInfo.entity.NuBaseInfo;
import com.nu.modules.nuBaseInfo.service.INuBaseInfoService;
import com.nu.utils.RabbitMQUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Component
public class NuBaseInfoMQListener {
@Autowired
private RabbitMQUtil rabbitMQUtil;
@Autowired
private ISysBaseAPI sysBaseAPI;
@Autowired
private INuBaseInfoService baseInfoService;
/**
* direct直连 只发给我的
*
* @param dto
*/
@RabbitListener(
bindings = @QueueBinding(
value = @Queue(name = "#{hldyAsyncDQNP.getQueueName()}"),
exchange = @Exchange(name = "hldy.hldy.sync", type = ExchangeTypes.DIRECT),
key = "#{hldyAsyncDQNP.getKeyName()}"
),
errorHandler = "nuBaseInfoMQErrorHandler"
)
public void handleMessage_self(NuBaseInfoMQDto dto) {
saveBaseInfo(dto);
}
/**
* 系统参数配置同步
* <p>
*
* @param dto
*/
private void saveBaseInfo(NuBaseInfoMQDto dto) {
//查询此业务系统的机构编码名称
String orgCode = "业务系统中未设置";
String orgName = "业务系统中未设置";
JSONObject deptInfo = sysBaseAPI.getDeptInfo();
orgCode = deptInfo.getString("code");
orgName = deptInfo.getString("name");
List<NuBaseInfo> syncList = ListUtil.of();
try {
syncList = baseInfoService.getSynchronized("multi-datasource1", orgCode);
baseInfoService.batchInsert(syncList);
} catch (Exception e) {
StatusMQDto statusMQDto = new StatusMQDto();
statusMQDto.setStatus(MQStatus.PROCESS_FAILED.getCode());
statusMQDto.setMessage(e.getMessage());
statusMQDto.setPrimaryKey(dto.getAsyncId());
statusMQDto.setOrgCode(orgCode);
statusMQDto.setOrgName(orgName);
rabbitMQUtil.sendToExchange("hldy.hldy", "hldy.async.result", statusMQDto);
throw new RuntimeException(e);
}
StatusMQDto statusMQDto = new StatusMQDto();
statusMQDto.setStatus(MQStatus.SUCCESS.getCode());
statusMQDto.setMessage("数据同步成功!");
statusMQDto.setPrimaryKey(dto.getAsyncId());
statusMQDto.setOrgCode(orgCode);
statusMQDto.setOrgName(orgName);
//将所有id转为逗号拼接字符串
statusMQDto.setNote(syncList.stream().map(NuBaseInfo::getId).map(Object::toString).collect(Collectors.joining(",")));
rabbitMQUtil.sendToExchange("hldy.hldy", "hldy.async.result", statusMQDto);
}
}

View File

@ -0,0 +1,19 @@
package com.nu.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Description: 护理单元
* @Author: jeecg-boot
* @Date: 2025-04-11
* @Version: V1.0
*/
@Data
public class NuBaseInfoMQDto implements Serializable {
private static final long serialVersionUID = 1L;
private String orgCode;
private String asyncId;
}

View File

@ -17,4 +17,6 @@ public class StatusMQDto {
private String primaryKey;
private String orgCode;
private String orgName;
//备注字段可存储个性化内容用于数据交互处理
private String note;
}

View File

@ -191,6 +191,12 @@ spring:
username: fw8864sshdang
password: uGDBkM25I6nZCNM2
driver-class-name: com.mysql.cj.jdbc.Driver
# 多数据源配置-试验田 TODO 需要创建对应只读账号 不同服务器间需要更改ip端口 另外注意是否采用了VPC
nuro:
url: jdbc:mysql://mysql8-prod:3306/nursing_unit?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: fw8864sshdang
password: uGDBkM25I6nZCNM2
driver-class-name: com.mysql.cj.jdbc.Driver
#redis 配置
redis:
database: 0