feat(core): 完善自动填充机制和时间格式化处理

- 替换 ServiceImpl 继承为 BaseService 以支持自动填充功能
- 在 HisBaseEntity 中添加 JsonFormat 注解统一时间格式化
- 重构 MybastisColumnsHandler 实现完整的自动填充逻辑,包括 createTime、updateTime、createBy、updateBy 和 tenantId 字段
- 添加详细的日志记录和异常处理机制
- 在 PractitionerAppServiceImpl 中增强租户ID和审计字段的设置逻辑
- 优化时间解析工具类 openhis.js 以正确处理 ISO 8601 格式时间字符串
- 更新数据库映射文件以支持下划线字段名映射
- 重构 SysUserServiceImpl 实现完整的审计字段自动填充机制
This commit is contained in:
2026-01-25 23:13:04 +08:00
parent ca043de624
commit ffce6f81c3
12 changed files with 372 additions and 158 deletions

View File

@@ -3,6 +3,7 @@ package com.core.common.core.domain;
import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@@ -27,6 +28,7 @@ public class HisBaseEntity implements Serializable {
/** 创建时间 */ /** 创建时间 */
@TableField(fill = FieldFill.INSERT) @TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime; private Date createTime;
/** 更新者 */ /** 更新者 */
@@ -35,6 +37,7 @@ public class HisBaseEntity implements Serializable {
/** 更新时间 */ /** 更新时间 */
@TableField(fill = FieldFill.UPDATE) @TableField(fill = FieldFill.UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime; private Date updateTime;
/** 租户ID */ /** 租户ID */

View File

@@ -2,6 +2,7 @@ package com.core.framework.config;
import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
@@ -9,7 +10,9 @@ import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInt
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.core.common.utils.SecurityUtils; import com.core.common.utils.SecurityUtils;
import com.core.framework.handler.MybastisColumnsHandler;
import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.LongValue;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
@@ -165,7 +168,8 @@ public class MybatisPlusConfig {
@Primary @Primary
public SqlSessionFactory sqlSessionFactory( public SqlSessionFactory sqlSessionFactory(
@Qualifier("dynamicDataSource") DataSource dataSource, @Qualifier("dynamicDataSource") DataSource dataSource,
MybatisPlusInterceptor mybatisPlusInterceptor) throws Exception { MybatisPlusInterceptor mybatisPlusInterceptor,
MetaObjectHandler metaObjectHandler) throws Exception { // 注入 MetaObjectHandler
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean(); MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource); sessionFactory.setDataSource(dataSource);
// 设置 mapper 文件位置 // 设置 mapper 文件位置
@@ -188,9 +192,22 @@ public class MybatisPlusConfig {
configuration.setLogImpl(org.apache.ibatis.logging.slf4j.Slf4jImpl.class); configuration.setLogImpl(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
sessionFactory.setConfiguration(configuration); sessionFactory.setConfiguration(configuration);
// 设置 MyBatis-Plus 的全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setMetaObjectHandler(metaObjectHandler);
sessionFactory.setGlobalConfig(globalConfig);
// 设置拦截器(通过参数注入避免循环依赖) // 设置拦截器(通过参数注入避免循环依赖)
sessionFactory.setPlugins(mybatisPlusInterceptor); sessionFactory.setPlugins(mybatisPlusInterceptor);
return sessionFactory.getObject(); return sessionFactory.getObject();
} }
/**
* 注册自动填充处理器
*/
@Bean
public MetaObjectHandler metaObjectHandler() {
return new MybastisColumnsHandler();
}
} }

View File

@@ -5,6 +5,8 @@ import com.core.common.core.domain.model.LoginUser;
import com.core.common.utils.SecurityUtils; import com.core.common.utils.SecurityUtils;
import com.core.framework.config.TenantContext; import com.core.framework.config.TenantContext;
import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.MetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
@@ -12,38 +14,97 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Date; import java.util.Date;
/**
* MyBatis-Plus 自动填充处理器
* 用于自动填充创建时间和更新时间,以及创建人和更新人
*/
@Component @Component
public class MybastisColumnsHandler implements MetaObjectHandler { public class MybastisColumnsHandler implements MetaObjectHandler {
// 设置数据新增时候的,字段自动赋值规则 private static final Logger logger = LoggerFactory.getLogger(MybastisColumnsHandler.class);
// 设置数据新增时的字段自动赋值规则
@Override @Override
public void insertFill(MetaObject metaObject) { public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); logger.info("开始执行 insertFill 自动填充");
String username = "system";
try { // 填充创建时间
LoginUser loginUser = SecurityUtils.getLoginUser(); Date currentTime = new Date();
if (loginUser != null) { this.strictInsertFill(metaObject, "createTime", Date.class, currentTime);
username = loginUser.getUsername(); this.strictInsertFill(metaObject, "create_time", Date.class, currentTime);
} logger.debug("已填充创建时间: {}", currentTime);
} catch (Exception ignored) {
} // 获取当前登录用户名
String username = getCurrentUsername();
logger.debug("获取到当前用户名: {}", username);
// 填充创建人
this.strictInsertFill(metaObject, "createBy", String.class, username); this.strictInsertFill(metaObject, "createBy", String.class, username);
this.strictInsertFill(metaObject, "tenantId", Integer.class, getCurrentTenantId()); this.strictInsertFill(metaObject, "create_by", String.class, username);
logger.debug("已填充创建人: {}", username);
// 确保tenantId被设置
Integer tenantId = getCurrentTenantId();
if (tenantId == null) {
throw new RuntimeException("无法获取当前租户ID请确保用户已登录或正确设置租户上下文");
}
this.strictInsertFill(metaObject, "tenantId", Integer.class, tenantId);
this.strictInsertFill(metaObject, "tenant_id", Integer.class, tenantId);
logger.debug("已填充租户ID: {}", tenantId);
logger.info("insertFill 自动填充完成");
} }
// 设置数据修改update时候的字段自动赋值规则 // 设置数据修改时的字段自动赋值规则
@Override @Override
public void updateFill(MetaObject metaObject) { public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); logger.info("开始执行 updateFill 自动填充");
String username = "system";
// 填充更新时间
Date currentTime = new Date();
this.strictUpdateFill(metaObject, "updateTime", Date.class, currentTime);
this.strictUpdateFill(metaObject, "update_time", Date.class, currentTime);
logger.debug("已填充更新时间: {}", currentTime);
// 填充更新人
String username = getCurrentUsername();
logger.debug("获取到当前用户名: {}", username);
this.strictUpdateFill(metaObject, "updateBy", String.class, username);
this.strictUpdateFill(metaObject, "update_by", String.class, username);
logger.debug("已填充更新人: {}", username);
logger.info("updateFill 自动填充完成");
}
/**
* 获取当前登录用户名
* @return 当前登录用户名,如果无法获取则返回 "system"
*/
private String getCurrentUsername() {
String username = "system"; // 默认值
try { try {
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null) { if (loginUser != null) {
username = loginUser.getUsername(); username = loginUser.getUsername();
logger.debug("从SecurityContext获取到用户名: {}", username);
} else {
logger.warn("SecurityContext中没有找到登录用户信息");
// 尝试从请求中获取用户信息
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
// 可以在这里添加额外的逻辑来从请求中获取用户信息
// 例如从请求头、session等获取用户信息
}
} }
} catch (Exception ignored) { } catch (Exception e) {
// 记录异常但不中断处理流程
logger.error("获取当前登录用户时发生异常: ", e);
} }
this.strictUpdateFill(metaObject, "updateBy", String.class, username);
return username;
} }
/** /**
@@ -60,10 +121,14 @@ public class MybastisColumnsHandler implements MetaObjectHandler {
// 获取当前登录用户的租户ID优先使用SecurityUtils中储存的LoginUser的租户ID // 获取当前登录用户的租户ID优先使用SecurityUtils中储存的LoginUser的租户ID
try { try {
if (SecurityUtils.getAuthentication() != null) { if (SecurityUtils.getAuthentication() != null) {
result = SecurityUtils.getLoginUser().getTenantId(); LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null) {
result = loginUser.getTenantId();
}
} }
} catch (Exception e) { } catch (Exception e) {
result = 1; // 默认租户ID // 记录异常但不中断处理
logger.error("获取当前登录用户租户ID时发生异常: ", e);
} }
if (result == null) { if (result == null) {
@@ -71,19 +136,31 @@ public class MybastisColumnsHandler implements MetaObjectHandler {
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
if (attributes != null) { if (attributes != null) {
HttpServletRequest request = attributes.getRequest(); HttpServletRequest request = attributes.getRequest();
// 从请求头获取租户ID假设header名称为"X-Tenant-ID" ; 登录接口前端把租户id放到请求头里 if (request != null) {
String tenantIdHeader = request.getHeader("X-Tenant-ID"); // 从请求头获取租户ID假设header名称为"X-Tenant-ID" ; 登录接口前端把租户id放到请求头里
String requestMethodName = request.getHeader("Request-Method-Name"); String tenantIdHeader = request.getHeader("X-Tenant-ID");
// 登录 String requestMethodName = request.getHeader("Request-Method-Name");
if ("login".equals(requestMethodName)) { // 登录
if (tenantIdHeader != null && !tenantIdHeader.isEmpty()) { if ("login".equals(requestMethodName)) {
result = Integer.parseInt(tenantIdHeader); if (tenantIdHeader != null && !tenantIdHeader.isEmpty()) {
try {
result = Integer.parseInt(tenantIdHeader);
} catch (NumberFormatException e) {
logger.error("解析请求头中的租户ID时发生异常: ", e);
}
}
} }
} }
} }
} }
} }
return result != null ? result : 1; // 默认租户ID // 如果仍然没有获取到租户ID返回默认值
if (result == null) {
logger.warn("未能获取当前租户ID将使用默认租户ID 1");
result = 1; // 默认租户ID
}
return result;
} }
} }

View File

@@ -10,6 +10,7 @@ import com.core.common.utils.SecurityUtils;
import com.core.common.utils.StringUtils; import com.core.common.utils.StringUtils;
import com.core.common.utils.bean.BeanValidators; import com.core.common.utils.bean.BeanValidators;
import com.core.common.utils.spring.SpringUtils; import com.core.common.utils.spring.SpringUtils;
import com.core.common.utils.AuditFieldUtil; // 引入我们创建的工具类
import com.core.system.domain.SysPost; import com.core.system.domain.SysPost;
import com.core.system.domain.SysUserPost; import com.core.system.domain.SysUserPost;
import com.core.system.domain.SysUserRole; import com.core.system.domain.SysUserRole;
@@ -55,6 +56,132 @@ public class SysUserServiceImpl implements ISysUserService {
@Autowired @Autowired
private ISysDeptService deptService; private ISysDeptService deptService;
/**
* 新增保存用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
@Transactional
public int insertUser(SysUser user) {
// 在保存前设置审计字段
AuditFieldUtil.setCreateInfo(user);
// 新增用户信息
int rows = userMapper.insertUser(user);
// 新增用户岗位关联
insertUserPost(user);
// 新增用户与角色管理
insertUserRole(user);
return rows;
}
/**
* 修改保存用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
@Transactional
public int updateUser(SysUser user) {
// 在更新前设置审计字段
AuditFieldUtil.setUpdateInfo(user);
Long userId = user.getUserId();
// 删除用户与角色关联
userRoleMapper.deleteUserRoleByUserId(userId);
// 新增用户与角色管理
insertUserRole(user);
// 删除用户与岗位关联
userPostMapper.deleteUserPostByUserId(userId);
// 新增用户与岗位管理
insertUserPost(user);
return userMapper.updateUser(user);
}
/**
* 注册用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
public boolean registerUser(SysUser user) {
// 在保存前设置审计字段
AuditFieldUtil.setCreateInfo(user);
return userMapper.insertUser(user) > 0;
}
/**
* 导入用户数据
*
* @param userList 用户数据列表
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
* @param operName 操作用户
* @return 结果
*/
@Override
public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName) {
if (StringUtils.isNull(userList) || userList.size() == 0) {
throw new ServiceException("导入用户数据不能为空!");
}
int successNum = 0;
int failureNum = 0;
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
for (SysUser user : userList) {
try {
// 验证是否存在这个用户
SysUser u = userMapper.selectUserByUserName(user.getUserName());
if (StringUtils.isNull(u)) {
BeanValidators.validateWithException(validator, user);
deptService.checkDeptDataScope(user.getDeptId());
String password = configService.selectConfigByKey("sys.user.initPassword");
user.setPassword(SecurityUtils.encryptPassword(password));
// 在导入用户时设置审计字段
AuditFieldUtil.setCreateInfo(user);
userMapper.insertUser(user);
successNum++;
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
} else if (isUpdateSupport) {
BeanValidators.validateWithException(validator, user);
checkUserAllowed(u);
checkUserDataScope(u.getUserId());
deptService.checkDeptDataScope(user.getDeptId());
user.setUserId(u.getUserId());
// 在更新用户时设置审计字段
AuditFieldUtil.setUpdateInfo(user);
userMapper.updateUser(user);
successNum++;
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
} else {
failureNum++;
failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
}
} catch (Exception e) {
failureNum++;
String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
failureMsg.append(msg + e.getMessage());
log.error(msg, e);
}
}
if (failureNum > 0) {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new ServiceException(failureMsg.toString());
} else {
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
}
return successMsg.toString();
}
// 以下是原有方法,保持不变
/** /**
* 根据条件分页查询用户列表 * 根据条件分页查询用户列表
* *
@@ -220,56 +347,6 @@ public class SysUserServiceImpl implements ISysUserService {
} }
} }
/**
* 新增保存用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
@Transactional
public int insertUser(SysUser user) {
// 新增用户信息
int rows = userMapper.insertUser(user);
// 新增用户岗位关联
insertUserPost(user);
// 新增用户与角色管理
insertUserRole(user);
return rows;
}
/**
* 注册用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
public boolean registerUser(SysUser user) {
return userMapper.insertUser(user) > 0;
}
/**
* 修改保存用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
@Transactional
public int updateUser(SysUser user) {
Long userId = user.getUserId();
// 删除用户与角色关联
userRoleMapper.deleteUserRoleByUserId(userId);
// 新增用户与角色管理
insertUserRole(user);
// 删除用户与岗位关联
userPostMapper.deleteUserPostByUserId(userId);
// 新增用户与岗位管理
insertUserPost(user);
return userMapper.updateUser(user);
}
/** /**
* 用户授权角色 * 用户授权角色
* *
@@ -425,66 +502,6 @@ public class SysUserServiceImpl implements ISysUserService {
return userMapper.deleteUserByIds(userIds); return userMapper.deleteUserByIds(userIds);
} }
/**
* 导入用户数据
*
* @param userList 用户数据列表
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
* @param operName 操作用户
* @return 结果
*/
@Override
public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName) {
if (StringUtils.isNull(userList) || userList.size() == 0) {
throw new ServiceException("导入用户数据不能为空!");
}
int successNum = 0;
int failureNum = 0;
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
for (SysUser user : userList) {
try {
// 验证是否存在这个用户
SysUser u = userMapper.selectUserByUserName(user.getUserName());
if (StringUtils.isNull(u)) {
BeanValidators.validateWithException(validator, user);
deptService.checkDeptDataScope(user.getDeptId());
String password = configService.selectConfigByKey("sys.user.initPassword");
user.setPassword(SecurityUtils.encryptPassword(password));
user.setCreateBy(operName);
userMapper.insertUser(user);
successNum++;
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
} else if (isUpdateSupport) {
BeanValidators.validateWithException(validator, user);
checkUserAllowed(u);
checkUserDataScope(u.getUserId());
deptService.checkDeptDataScope(user.getDeptId());
user.setUserId(u.getUserId());
user.setUpdateBy(operName);
userMapper.updateUser(user);
successNum++;
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
} else {
failureNum++;
failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
}
} catch (Exception e) {
failureNum++;
String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
failureMsg.append(msg + e.getMessage());
log.error(msg, e);
}
}
if (failureNum > 0) {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new ServiceException(failureMsg.toString());
} else {
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
}
return successMsg.toString();
}
/** /**
* 扩展属性 * 扩展属性
* *

View File

@@ -195,6 +195,7 @@
<if test="status != null and status != ''">status,</if> <if test="status != null and status != ''">status,</if>
<if test="createBy != null and createBy != ''">create_by,</if> <if test="createBy != null and createBy != ''">create_by,</if>
<if test="remark != null and remark != ''">remark,</if> <if test="remark != null and remark != ''">remark,</if>
tenant_id,
create_time create_time
)values( )values(
<if test="userId != null and userId != ''">#{userId},</if> <if test="userId != null and userId != ''">#{userId},</if>
@@ -209,6 +210,7 @@
<if test="status != null and status != ''">#{status},</if> <if test="status != null and status != ''">#{status},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if> <if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="remark != null and remark != ''">#{remark},</if> <if test="remark != null and remark != ''">#{remark},</if>
#{tenantId},
now() now()
) )
</insert> </insert>

View File

@@ -92,6 +92,20 @@ public class PractitionerAppServiceImpl implements IPractitionerAppService {
bizUser.setPassword(SecurityUtils.encryptPassword(userAndPractitionerDto.getPassword())); // 密码 bizUser.setPassword(SecurityUtils.encryptPassword(userAndPractitionerDto.getPassword())); // 密码
bizUser.setStatus(userAndPractitionerDto.getStatus()); // 状态 bizUser.setStatus(userAndPractitionerDto.getStatus()); // 状态
bizUser.setRemark(userAndPractitionerDto.getRemark()); // 备注 bizUser.setRemark(userAndPractitionerDto.getRemark()); // 备注
// 确保tenantId被设置如果自动填充机制未能正确填充
if (bizUser.getTenantId() == null) {
try {
bizUser.setTenantId(SecurityUtils.getLoginUser().getTenantId());
} catch (Exception e) {
// 如果无法获取当前登录用户则使用默认租户ID
bizUser.setTenantId(1); // 默认租户ID
}
}
// 确保审计字段被设置
com.core.common.utils.AuditFieldUtil.setCreateInfo(bizUser);
iBizUserService.save(bizUser); iBizUserService.save(bizUser);
Long userId = Long userId =
iBizUserService.getOne(new LambdaQueryWrapper<BizUser>().eq(BizUser::getUserName, userName)).getUserId(); // 用户id iBizUserService.getOne(new LambdaQueryWrapper<BizUser>().eq(BizUser::getUserName, userName)).getUserId(); // 用户id
@@ -119,6 +133,17 @@ public class PractitionerAppServiceImpl implements IPractitionerAppService {
practitioner.setAddress(userAndPractitionerDto.getAddress()); // 地址 practitioner.setAddress(userAndPractitionerDto.getAddress()); // 地址
practitioner.setYbNo(userAndPractitionerDto.getYbNo()); // 医保码 practitioner.setYbNo(userAndPractitionerDto.getYbNo()); // 医保码
practitioner.setUserId(userId); // 系统用户id practitioner.setUserId(userId); // 系统用户id
// 确保tenantId被设置如果自动填充机制未能正确填充
if (practitioner.getTenantId() == null) {
try {
practitioner.setTenantId(SecurityUtils.getLoginUser().getTenantId());
} catch (Exception e) {
// 如果无法获取当前登录用户则使用默认租户ID
practitioner.setTenantId(1); // 默认租户ID
}
}
// 责任科室 // 责任科室
List<PractitionerOrgAndLocationDto> responsibilityOrgDtoList = List<PractitionerOrgAndLocationDto> responsibilityOrgDtoList =
userAndPractitionerDto.getResponsibilityOrgDtoList(); userAndPractitionerDto.getResponsibilityOrgDtoList();
@@ -295,6 +320,20 @@ public class PractitionerAppServiceImpl implements IPractitionerAppService {
bizUser.setSex(sex); // 性别 bizUser.setSex(sex); // 性别
bizUser.setStatus(userAndPractitionerDto.getStatus()); // 状态 bizUser.setStatus(userAndPractitionerDto.getStatus()); // 状态
bizUser.setRemark(userAndPractitionerDto.getRemark()); // 备注 bizUser.setRemark(userAndPractitionerDto.getRemark()); // 备注
// 确保tenantId被设置如果自动填充机制未能正确填充
if (bizUser.getTenantId() == null) {
try {
bizUser.setTenantId(SecurityUtils.getLoginUser().getTenantId());
} catch (Exception e) {
// 如果无法获取当前登录用户则使用默认租户ID
bizUser.setTenantId(1); // 默认租户ID
}
}
// 确保审计字段被设置
com.core.common.utils.AuditFieldUtil.setUpdateInfo(bizUser);
iBizUserService.update(bizUser, new LambdaQueryWrapper<BizUser>().eq(BizUser::getUserId, userId)); iBizUserService.update(bizUser, new LambdaQueryWrapper<BizUser>().eq(BizUser::getUserId, userId));
// 先删除,再新增 sys_user_role // 先删除,再新增 sys_user_role
practitionerAppAppMapper.delUserRole(userId); practitionerAppAppMapper.delUserRole(userId);
@@ -316,6 +355,17 @@ public class PractitionerAppServiceImpl implements IPractitionerAppService {
practitioner.setAddress(userAndPractitionerDto.getAddress()); // 地址 practitioner.setAddress(userAndPractitionerDto.getAddress()); // 地址
practitioner.setYbNo(userAndPractitionerDto.getYbNo()); // 医保码 practitioner.setYbNo(userAndPractitionerDto.getYbNo()); // 医保码
practitioner.setUserId(userId); // 系统用户id practitioner.setUserId(userId); // 系统用户id
// 确保tenantId被设置如果自动填充机制未能正确填充
if (practitioner.getTenantId() == null) {
try {
practitioner.setTenantId(SecurityUtils.getLoginUser().getTenantId());
} catch (Exception e) {
// 如果无法获取当前登录用户则使用默认租户ID
practitioner.setTenantId(1); // 默认租户ID
}
}
// 责任科室 // 责任科室
List<PractitionerOrgAndLocationDto> responsibilityOrgDtoList = List<PractitionerOrgAndLocationDto> responsibilityOrgDtoList =
userAndPractitionerDto.getResponsibilityOrgDtoList(); userAndPractitionerDto.getResponsibilityOrgDtoList();
@@ -446,6 +496,17 @@ public class PractitionerAppServiceImpl implements IPractitionerAppService {
Practitioner practitioner = new Practitioner(); Practitioner practitioner = new Practitioner();
practitioner.setId(practitionerId); practitioner.setId(practitionerId);
practitioner.setOrgId(orgId); practitioner.setOrgId(orgId);
// 确保tenantId被设置如果自动填充机制未能正确填充
if (practitioner.getTenantId() == null) {
try {
practitioner.setTenantId(SecurityUtils.getLoginUser().getTenantId());
} catch (Exception e) {
// 如果无法获取当前登录用户则使用默认租户ID
practitioner.setTenantId(1); // 默认租户ID
}
}
iPractitionerService.updateById(practitioner); iPractitionerService.updateById(practitioner);
return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"切换科室"})); return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"切换科室"}));
} }

View File

@@ -112,6 +112,12 @@ public class UserAndPractitionerDto {
private Long orgId; private Long orgId;
private String orgId_dictText; private String orgId_dictText;
/**
* 创建时间
*/
@com.fasterxml.jackson.annotation.JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** /**
* 责任科室 * 责任科室
*/ */

View File

@@ -23,7 +23,8 @@
T3.org_id, T3.org_id,
T3.phar_prac_cert_no, T3.phar_prac_cert_no,
T3.dr_profttl_code, T3.dr_profttl_code,
T3.signature T3.signature,
T3.create_time
from ( from (
SELECT T1.tenant_id, SELECT T1.tenant_id,
T1.id AS practitioner_id, T1.id AS practitioner_id,
@@ -43,7 +44,8 @@
T1.org_id, T1.org_id,
T1.phar_prac_cert_no, T1.phar_prac_cert_no,
T1.dr_profttl_code, T1.dr_profttl_code,
T1.signature T1.signature,
T2.create_time
FROM adm_practitioner AS T1 FROM adm_practitioner AS T1
LEFT JOIN sys_user AS T2 ON T2.user_id = T1.user_id LEFT JOIN sys_user AS T2 ON T2.user_id = T1.user_id
AND T2.delete_flag = '0' AND T2.delete_flag = '0'

View File

@@ -15,7 +15,7 @@
<setting name="logImpl" value="SLF4J"/> <setting name="logImpl" value="SLF4J"/>
<!-- <setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>--> <!-- <setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>-->
<!-- 使用驼峰命名法转换字段 --> <!-- 使用驼峰命名法转换字段 -->
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> --> <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings> </settings>
</configuration> </configuration>

View File

@@ -1,6 +1,6 @@
package com.openhis.administration.service.impl; package com.openhis.administration.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.core.common.service.BaseService;
import com.openhis.administration.domain.BizUser; import com.openhis.administration.domain.BizUser;
import com.openhis.administration.mapper.BizUserMapper; import com.openhis.administration.mapper.BizUserMapper;
import com.openhis.administration.service.IBizUserService; import com.openhis.administration.service.IBizUserService;
@@ -13,6 +13,6 @@ import org.springframework.stereotype.Service;
* @date 2025-02-20 * @date 2025-02-20
*/ */
@Service @Service
public class BizUserServiceImpl extends ServiceImpl<BizUserMapper, BizUser> implements IBizUserService { public class BizUserServiceImpl extends BaseService<BizUserMapper, BizUser> implements IBizUserService {
} }

View File

@@ -2,8 +2,8 @@ package com.openhis.administration.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.core.common.enums.DelFlag; import com.core.common.enums.DelFlag;
import com.core.common.service.BaseService;
import com.openhis.administration.domain.Practitioner; import com.openhis.administration.domain.Practitioner;
import com.openhis.administration.mapper.PractitionerMapper; import com.openhis.administration.mapper.PractitionerMapper;
import com.openhis.administration.service.IPractitionerService; import com.openhis.administration.service.IPractitionerService;
@@ -18,7 +18,7 @@ import java.util.List;
* @date 2025-02-20 * @date 2025-02-20
*/ */
@Service @Service
public class PractitionerServiceImpl extends ServiceImpl<PractitionerMapper, Practitioner> public class PractitionerServiceImpl extends BaseService<PractitionerMapper, Practitioner>
implements IPractitionerService { implements IPractitionerService {
/** /**

View File

@@ -18,13 +18,42 @@ export function parseTime(time, pattern) {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time) time = parseInt(time)
} else if (typeof time === 'string') { } else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), ''); // 处理 ISO 8601 格式的时间字符串,保留时区信息
// 例如:"2026-01-19T01:59:27.239+08:00"
if (time.includes('T')) {
// 直接使用 ISO 8601 格式的字符串创建日期对象
date = new Date(time)
// 如果日期无效,尝试其他格式
if (isNaN(date.getTime())) {
// 移除毫秒部分但保留时区信息
time = time.replace(/\.\d{3}/, '')
date = new Date(time)
}
} else {
// 处理其他格式的字符串
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
}
}
if (!date || isNaN(date.getTime())) {
// 如果还没有创建有效的日期对象,则基于处理后的字符串创建
if (typeof time === 'string') {
date = new Date(time)
}
} }
if ((typeof time === 'number') && (time.toString().length === 10)) { if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000 time = time * 1000
} }
date = new Date(time) if (!date || isNaN(date.getTime())) {
// 最终尝试使用原始时间值
date = new Date(time)
}
} }
// 检查日期是否有效
if (isNaN(date.getTime())) {
return null
}
const formatObj = { const formatObj = {
y: date.getFullYear(), y: date.getFullYear(),
m: date.getMonth() + 1, m: date.getMonth() + 1,