diff --git a/src/main/java/cn/yinlihupo/common/config/JsonConfig.java b/src/main/java/cn/yinlihupo/common/config/JsonConfig.java new file mode 100644 index 0000000..5292423 --- /dev/null +++ b/src/main/java/cn/yinlihupo/common/config/JsonConfig.java @@ -0,0 +1,60 @@ +package cn.yinlihupo.common.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import org.springframework.boot.jackson.JsonComponent; +import org.springframework.context.annotation.Bean; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; + +/** + * Spring MVC Json 配置 + */ +@JsonComponent +public class JsonConfig { + + /** + * 添加 Long 转 json 精度丢失的配置 + * 配置 LocalDateTime 支持多种日期时间格式 + */ + @Bean + public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { + ObjectMapper objectMapper = builder.createXmlMapper(false).build(); + + // Long 类型序列化配置 + SimpleModule module = new SimpleModule(); + module.addSerializer(Long.class, ToStringSerializer.instance); + module.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(module); + + // Java 8 日期时间类型支持 + JavaTimeModule javaTimeModule = new JavaTimeModule(); + + // 配置 LocalDateTime 的序列化和反序列化格式 + // 支持 "yyyy-MM-dd HH:mm:ss" 和 "yyyy-MM-dd HH:mm" 两种格式 + DateTimeFormatter deserializeFormatter = new DateTimeFormatterBuilder() + .appendPattern("yyyy-MM-dd HH:mm") + .optionalStart() + .appendPattern(":ss") + .optionalEnd() + .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) // 如果没有秒,默认00秒 + .toFormatter(); + + DateTimeFormatter serializeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(serializeFormatter)); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(deserializeFormatter)); + + objectMapper.registerModule(javaTimeModule); + + return objectMapper; + } +} diff --git a/src/main/java/cn/yinlihupo/common/config/MybatisPlusConfig.java b/src/main/java/cn/yinlihupo/common/config/MybatisPlusConfig.java new file mode 100644 index 0000000..fdaf50d --- /dev/null +++ b/src/main/java/cn/yinlihupo/common/config/MybatisPlusConfig.java @@ -0,0 +1,25 @@ +package cn.yinlihupo.common.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * MyBatis-Plus 配置类 + */ +@Configuration +public class MybatisPlusConfig { + + /** + * 添加分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 如果配置多个插件, 注意分页插件要放在最后 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL)); + return interceptor; + } +} diff --git a/src/main/java/cn/yinlihupo/common/util/PhoneUtils.java b/src/main/java/cn/yinlihupo/common/util/PhoneUtils.java new file mode 100644 index 0000000..6b4b2ae --- /dev/null +++ b/src/main/java/cn/yinlihupo/common/util/PhoneUtils.java @@ -0,0 +1,90 @@ +package cn.yinlihupo.common.util; + +/** + * 手机号工具类 + * 提供手机号格式化、验证等通用方法 + */ +public class PhoneUtils { + + /** + * 中国大陆手机号前缀 + */ + private static final String CHINA_MOBILE_PREFIX = "+86"; + + /** + * 去除手机号中的国家码前缀(如 +86) + * + * @param phone 原始手机号 + * @return 去除前缀后的手机号 + */ + public static String normalizePhone(String phone) { + if (phone == null || phone.isEmpty()) { + return phone; + } + + // 去除 +86 前缀 + if (phone.startsWith(CHINA_MOBILE_PREFIX)) { + return phone.substring(3); + } + + return phone; + } + + /** + * 添加中国大陆手机号前缀(+86) + * + * @param phone 手机号 + * @return 添加前缀后的手机号 + */ + public static String addChinaPrefix(String phone) { + if (phone == null || phone.isEmpty()) { + return phone; + } + + // 如果已经有前缀,直接返回 + if (phone.startsWith(CHINA_MOBILE_PREFIX)) { + return phone; + } + + return CHINA_MOBILE_PREFIX + phone; + } + + /** + * 验证手机号格式(中国大陆) + * 简单验证:1开头,11位数字 + * + * @param phone 手机号 + * @return true-格式正确, false-格式错误 + */ + public static boolean isValidChinaPhone(String phone) { + if (phone == null || phone.isEmpty()) { + return false; + } + + // 先去除前缀 + String normalizedPhone = normalizePhone(phone); + + // 验证:1开头,11位数字 + return normalizedPhone.matches("^1[3-9]\\d{9}$"); + } + + /** + * 隐藏手机号中间4位 + * + * @param phone 手机号 + * @return 隐藏后的手机号,如:138****8888 + */ + public static String maskPhone(String phone) { + if (phone == null || phone.isEmpty()) { + return phone; + } + + String normalizedPhone = normalizePhone(phone); + + if (normalizedPhone.length() != 11) { + return phone; + } + + return normalizedPhone.substring(0, 3) + "****" + normalizedPhone.substring(7); + } +} diff --git a/src/main/java/cn/yinlihupo/controller/system/UserRoleController.java b/src/main/java/cn/yinlihupo/controller/system/UserRoleController.java index 64e2fb4..dabde16 100644 --- a/src/main/java/cn/yinlihupo/controller/system/UserRoleController.java +++ b/src/main/java/cn/yinlihupo/controller/system/UserRoleController.java @@ -14,6 +14,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.time.LocalDateTime; @@ -42,15 +43,21 @@ public class UserRoleController { @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) String keyword) { - + Page page = new Page<>(pageNum, pageSize); - List users = userMapper.selectPageList(null, null, keyword); - - // 手动设置分页结果 - page.setRecords(users); - page.setTotal(users.size()); - - return ResultUtils.success("查询成功", page); + // 使用MyBatis-Plus分页插件,将page作为第一个参数传入 + Page resultPage = userMapper.selectPage(page, new LambdaQueryWrapper() + .eq(SysUser::getDeleted, 0) + .and(StringUtils.hasText(keyword), qw -> qw + .like(SysUser::getUsername, keyword) + .or() + .like(SysUser::getRealName, keyword) + .or() + .like(SysUser::getPhone, keyword) + ) + .orderByDesc(SysUser::getCreateTime)); + + return ResultUtils.success("查询成功", resultPage); } /** diff --git a/src/main/java/cn/yinlihupo/service/system/impl/FeishuAuthServiceImpl.java b/src/main/java/cn/yinlihupo/service/system/impl/FeishuAuthServiceImpl.java index d9e3d0c..d54ee2a 100644 --- a/src/main/java/cn/yinlihupo/service/system/impl/FeishuAuthServiceImpl.java +++ b/src/main/java/cn/yinlihupo/service/system/impl/FeishuAuthServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.http.HttpResponse; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import cn.yinlihupo.common.config.FeishuConfig; +import cn.yinlihupo.common.util.PhoneUtils; import cn.yinlihupo.domain.entity.SysUser; import cn.yinlihupo.mapper.SysPermissionMapper; import cn.yinlihupo.mapper.SysUserMapper; @@ -84,6 +85,9 @@ public class FeishuAuthServiceImpl implements FeishuAuthService { String email = userInfo.getStr("email"); String openId = userInfo.getStr("open_id"); + // 去除手机号前缀 +86 + phone = PhoneUtils.normalizePhone(phone); + log.info("飞书用户信息: phone={}, name={}, openId={}", phone, realName, openId); // 5. 根据手机号获取或创建用户