diff --git a/.gitignore b/.gitignore index 8579c6a..7f470a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ target/ +logs/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/ diff --git a/ebike-operations/src/main/java/com/cdzy/operations/component/EbikeTenantFactory.java b/ebike-operations/src/main/java/com/cdzy/operations/component/EbikeTenantFactory.java index 8e6d463..49e4b10 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/component/EbikeTenantFactory.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/component/EbikeTenantFactory.java @@ -16,35 +16,43 @@ import java.util.TimeZone; public class EbikeTenantFactory implements TenantFactory { public Object[] getTenantIds() { - if (StpUtil.isLogin()) { - RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); - Object attribute = attributes.getAttribute("tenantId", RequestAttributes.SCOPE_REQUEST); - if (attribute != null) { - String id = (String) StpUtil.getLoginId(); - Object object = StpUtil.getSessionByLoginId(id).get(id); - ObjectMapper objectMapper = new ObjectMapper() - .registerModule(new JavaTimeModule()) - .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - .setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); - CommonStaffInfo staffInfo = objectMapper.convertValue(object, CommonStaffInfo.class); - List roles = staffInfo.getRoles(); - boolean isSysAdmin = false; - for (CommonEbikeRole role : roles) { - if (role.getSysAdmin()) { - isSysAdmin = true; - break; + try { + if (StpUtil.isLogin()) { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + if (attributes != null) { + Object attribute = attributes.getAttribute("tenantId", RequestAttributes.SCOPE_REQUEST); + String id = (String) StpUtil.getLoginId(); + Object object = StpUtil.getSessionByLoginId(id).get(id); + ObjectMapper objectMapper = new ObjectMapper() + .registerModule(new JavaTimeModule()) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + CommonStaffInfo staffInfo = objectMapper.convertValue(object, CommonStaffInfo.class); + List roles = staffInfo.getRoles(); + boolean isSysAdmin = false; + for (CommonEbikeRole role : roles) { + if (role.getSysAdmin()) { + isSysAdmin = true; + break; + } + } + long tenantId = 0; + if (attribute != null) { + tenantId = Long.parseLong(attribute.toString()); + } + //系统管理员 + if (isSysAdmin) { + return null; + } else { + return new Object[]{tenantId}; } } - long tenantId = Long.parseLong(attribute.toString()); - //系统管理员 - if (isSysAdmin) { - return null; - } else { - return new Object[]{tenantId}; - } - } + } + return null; + } catch (Exception e) { + return null; } - return null; + } } \ No newline at end of file diff --git a/ebike-operations/src/main/java/com/cdzy/operations/component/SafeOrderExpirationListener.java b/ebike-operations/src/main/java/com/cdzy/operations/component/SafeOrderExpirationListener.java index 5504508..095bc5f 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/component/SafeOrderExpirationListener.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/component/SafeOrderExpirationListener.java @@ -164,6 +164,10 @@ public class SafeOrderExpirationListener { .where(EBIKE_BIKE_ORDER.HANDLE_STATE.eq(OrderHandleState.PROCESSED)) .where(EBIKE_BIKE_ORDER.DISPATCH_STATE.eq(OrderDispatchState.PROCESSED)); EbikeBikeOrder bikeOrder = orderService.getOne(query); + if (bikeOrder == null) { + log.error("处理工单业务异常,不存在满足处理条件的工单: orderId={}", orderId); + return; + } bikeOrder.setDispatchState(OrderDispatchState.INEFFECTIVE); orderService.updateById(bikeOrder); } catch (Exception e) { diff --git a/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeBikeOrderController.java b/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeBikeOrderController.java index 8ac18cf..169a75b 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeBikeOrderController.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeBikeOrderController.java @@ -276,6 +276,17 @@ public class EbikeBikeOrderController { } + /** + * 有效调度工单统计 + * + * @return 操作结果 + */ + @GetMapping("effectiveDispatchOrder") + public JsonResult> effectiveDispatchOrder(@RequestBody EffectiveDispatchOrderVo effectiveDispatchOrderVo) { + List list = ebikeBikeOrderService.effectiveDispatchOrder(effectiveDispatchOrderVo); + return JsonResult.success(list); + } + /** * 工单看板 * diff --git a/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeSiteController.java b/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeSiteController.java index 0ab3e26..2e3ef7d 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeSiteController.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeSiteController.java @@ -13,6 +13,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Objects; import static com.cdzy.operations.model.entity.table.EbikeSiteTableDef.EBIKE_SITE; @@ -72,8 +73,10 @@ public class EbikeSiteController { * @return 所有数据 */ @GetMapping("list") - public JsonResult list() { - List list = ebikeSiteService.list(); + public JsonResult list(Long regionId) { + QueryWrapper queryWrapper = QueryWrapper.create() + .where(EBIKE_SITE.REGION_ID.eq(regionId, Objects.nonNull(regionId))); + List list = ebikeSiteService.list(queryWrapper); return JsonResult.success(list); } diff --git a/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EffectiveDispatchOrderDto.java b/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EffectiveDispatchOrderDto.java new file mode 100644 index 0000000..e28c10e --- /dev/null +++ b/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EffectiveDispatchOrderDto.java @@ -0,0 +1,33 @@ +package com.cdzy.operations.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author attiya + * @since 2025-12-23 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EffectiveDispatchOrderDto { + + /** + * 用户名 + */ + private String username; + + /** + * 用户名 + */ + private String staffId; + + /** + * 有效调度工单总数 + */ + private Integer count; + +} diff --git a/ebike-operations/src/main/java/com/cdzy/operations/model/vo/EffectiveDispatchOrderVo.java b/ebike-operations/src/main/java/com/cdzy/operations/model/vo/EffectiveDispatchOrderVo.java new file mode 100644 index 0000000..b1d3973 --- /dev/null +++ b/ebike-operations/src/main/java/com/cdzy/operations/model/vo/EffectiveDispatchOrderVo.java @@ -0,0 +1,29 @@ +package com.cdzy.operations.model.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author attiya + * @since 2025-12-23 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EffectiveDispatchOrderVo { + + /** + * 开始时间 + */ + private LocalDateTime startTime; + + /** + * 结束时间 + */ + private LocalDateTime endTime; +} diff --git a/ebike-operations/src/main/java/com/cdzy/operations/service/EbikeBikeOrderService.java b/ebike-operations/src/main/java/com/cdzy/operations/service/EbikeBikeOrderService.java index dad4e79..9db2c9c 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/service/EbikeBikeOrderService.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/service/EbikeBikeOrderService.java @@ -1,9 +1,6 @@ package com.cdzy.operations.service; -import com.cdzy.operations.model.dto.EbikeBikeOrderInfoDto; -import com.cdzy.operations.model.dto.EbikeOrderBikeListDto; -import com.cdzy.operations.model.dto.EbikeOrderBikeInfoDto; -import com.cdzy.operations.model.dto.EbikeOrderBulletinBoardInfo; +import com.cdzy.operations.model.dto.*; import com.cdzy.operations.model.entity.EbikeBikeOrder; import com.cdzy.operations.model.entity.EbikeRegion; import com.cdzy.operations.model.vo.*; @@ -133,4 +130,11 @@ public interface EbikeBikeOrderService extends IService { * 工单看板 */ EbikeOrderBulletinBoardInfo bulletinBoard(); + + /** + * 有效调度工单统计 + * @param effectiveDispatchOrderVo 筛选信息 + * @return 统计结果 + */ + List effectiveDispatchOrder(EffectiveDispatchOrderVo effectiveDispatchOrderVo); } diff --git a/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeOrderServiceImpl.java b/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeOrderServiceImpl.java index b741283..52331b8 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeOrderServiceImpl.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeOrderServiceImpl.java @@ -6,10 +6,7 @@ import com.cdzy.common.ex.EbikeException; import com.cdzy.common.model.dto.ResGPSDto; import com.cdzy.operations.enums.*; import com.cdzy.operations.mapper.*; -import com.cdzy.operations.model.dto.EbikeBikeOrderInfoDto; -import com.cdzy.operations.model.dto.EbikeOrderBikeInfoDto; -import com.cdzy.operations.model.dto.EbikeOrderBikeListDto; -import com.cdzy.operations.model.dto.EbikeOrderBulletinBoardInfo; +import com.cdzy.operations.model.dto.*; import com.cdzy.operations.model.entity.*; import com.cdzy.operations.model.vo.*; import com.cdzy.operations.service.EbikeBikeOrderService; @@ -34,7 +31,11 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.*; +import java.util.concurrent.TimeUnit; import static com.cdzy.operations.model.entity.table.EbikeBatteryInfoTableDef.EBIKE_BATTERY_INFO; import static com.cdzy.operations.model.entity.table.EbikeBikeInfoTableDef.EBIKE_BIKE_INFO; @@ -104,6 +105,9 @@ public class EbikeBikeOrderServiceImpl extends ServiceImpl fileUrls = doneDispatchOrderVo.getFileUrls(); List list = new ArrayList<>(); @@ -596,7 +602,11 @@ public class EbikeBikeOrderServiceImpl extends ServiceImpl list = ebikeOrderFileMapper.selectListByQueryAs(queryWrapper,String.class); + .where(EBIKE_ORDER_FILE.ORDER_ID.eq(bikeOrder.getOrderId())); + List list = ebikeOrderFileMapper.selectListByQueryAs(queryWrapper, String.class); queryWrapper.clear(); queryWrapper.select(EBIKE_ORDER_PART.ORDER_PART) - .where(EBIKE_ORDER_PART.ORDER_ID.eq( bikeOrder.getOrderId())); + .where(EBIKE_ORDER_PART.ORDER_ID.eq(bikeOrder.getOrderId())); List parts = ebikeOrderPartMapper.selectListByQueryAs(queryWrapper, Integer.class); EbikeBikeOrder ebikeBikeOrder = EbikeBikeOrder.builder() @@ -753,6 +763,27 @@ public class EbikeBikeOrderServiceImpl extends ServiceImpl effectiveDispatchOrder(EffectiveDispatchOrderVo effectiveDispatchOrderVo) { + + if (effectiveDispatchOrderVo.getStartTime() == null) { + effectiveDispatchOrderVo.setStartTime(LocalDateTime.now().toLocalDate().withDayOfMonth(1).atStartOfDay()); + } + + if (effectiveDispatchOrderVo.getEndTime() == null) { + effectiveDispatchOrderVo.setEndTime(LocalDateTime.now().toLocalDate().withDayOfMonth(LocalDate.now().lengthOfMonth()).atTime(LocalTime.MAX)); + } + + QueryWrapper queryWrapper = QueryWrapper.create() + .select(QueryMethods.count().as(EffectiveDispatchOrderDto::getCount),EBIKE_BIKE_ORDER.RECEIVER_ID.as(EffectiveDispatchOrderDto::getStaffId)) + .where(EBIKE_BIKE_ORDER.HANDLE_AT.between(effectiveDispatchOrderVo.getStartTime(), effectiveDispatchOrderVo.getEndTime())) + .where(EBIKE_BIKE_ORDER.ORDER_TYPE.eq(BikeOrderType.DISPATCH)) + .where(EBIKE_BIKE_ORDER.DISPATCH_STATE.eq(OrderDispatchState.EFFECTIVE)) + .groupBy(EBIKE_BIKE_ORDER.RECEIVER_ID) + .orderBy("count",true); + return ebikeBikeOrderMapper.selectListByQueryAs(queryWrapper, EffectiveDispatchOrderDto.class); + } + EbikeBikeInfo checkBikeCode(String bikeCode) { QueryWrapper queryWrapper = QueryWrapper.create() .where(EBIKE_BIKE_INFO.BIKE_CODE.eq(bikeCode)) diff --git a/ebike-operations/src/main/resources/application-dev.yml b/ebike-operations/src/main/resources/application-dev.yml index 93e99c8..7dbf864 100644 --- a/ebike-operations/src/main/resources/application-dev.yml +++ b/ebike-operations/src/main/resources/application-dev.yml @@ -117,8 +117,15 @@ minio: show-url: https://www.cdzhuojing.cn/file logging: + level: + root: INFO + org.springframework.web: WARN + org.mybatis: DEBUG # 查看MyBatis SQL语句 + file: + name: logs/${spring.application.name}.log # 输出到文件(默认追加) pattern: - dateformat: yyyy-MM-dd HH:mm:ss.SSS # 包含毫秒 + console: "%d{yyyy-MM-dd HH:mm:ss} - %highlight(%-5level) [%thread] %cyan(%logger{36}) : %msg%n" + file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" geo-coding: api-url: https://restapi.amap.com/v3/geocode diff --git a/ebike-operations/src/test/java/com/cdzy/operations/EbikeOperationsApplicationTests.java b/ebike-operations/src/test/java/com/cdzy/operations/EbikeOperationsApplicationTests.java index 620f26f..ca54117 100644 --- a/ebike-operations/src/test/java/com/cdzy/operations/EbikeOperationsApplicationTests.java +++ b/ebike-operations/src/test/java/com/cdzy/operations/EbikeOperationsApplicationTests.java @@ -1,14 +1,20 @@ package com.cdzy.operations; +import com.cdzy.operations.utils.RedisUtil; +import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class EbikeOperationsApplicationTests { + @Resource + RedisUtil redisUtil; + @Test void contextLoads() { + redisUtil.releaseDispatchLock("bike:dispatch:lock:360967408603103232"); } diff --git a/ebike-staff/src/main/java/com/cdzy/staff/component/EbikeTenantFactory.java b/ebike-staff/src/main/java/com/cdzy/staff/component/EbikeTenantFactory.java index 244bcb3..cddbc6e 100644 --- a/ebike-staff/src/main/java/com/cdzy/staff/component/EbikeTenantFactory.java +++ b/ebike-staff/src/main/java/com/cdzy/staff/component/EbikeTenantFactory.java @@ -16,35 +16,43 @@ import java.util.TimeZone; public class EbikeTenantFactory implements TenantFactory { public Object[] getTenantIds() { - if (StpUtil.isLogin()) { - RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); - Object attribute = attributes.getAttribute("tenantId", RequestAttributes.SCOPE_REQUEST); - if (attribute != null) { - String id = (String) StpUtil.getLoginId(); - Object object = StpUtil.getSessionByLoginId(id).get(id); - ObjectMapper objectMapper = new ObjectMapper() - .registerModule(new JavaTimeModule()) - .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - .setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); - CommonStaffInfo staffInfo = objectMapper.convertValue(object, CommonStaffInfo.class); - List roles = staffInfo.getRoles(); - boolean isSysAdmin = false; - for (CommonEbikeRole role : roles) { - if (role.getSysAdmin()) { - isSysAdmin = true; - break; + try { + if (StpUtil.isLogin()) { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + if (attributes != null) { + Object attribute = attributes.getAttribute("tenantId", RequestAttributes.SCOPE_REQUEST); + String id = (String) StpUtil.getLoginId(); + Object object = StpUtil.getSessionByLoginId(id).get(id); + ObjectMapper objectMapper = new ObjectMapper() + .registerModule(new JavaTimeModule()) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + CommonStaffInfo staffInfo = objectMapper.convertValue(object, CommonStaffInfo.class); + List roles = staffInfo.getRoles(); + boolean isSysAdmin = false; + for (CommonEbikeRole role : roles) { + if (role.getSysAdmin()) { + isSysAdmin = true; + break; + } + } + long tenantId = 0; + if (attribute != null) { + tenantId = Long.parseLong(attribute.toString()); + } + //系统管理员 + if (isSysAdmin) { + return null; + } else { + return new Object[]{tenantId}; } } - long tenantId = Long.parseLong(attribute.toString()); - //系统管理员 - if (isSysAdmin) { - return null; - } else { - return new Object[]{tenantId}; - } - } + } + return null; + } catch (Exception e) { + return null; } - return null; + } } \ No newline at end of file diff --git a/ebike-user/src/main/java/com/cdzy/user/controller/EbikeReportRecordController.java b/ebike-user/src/main/java/com/cdzy/user/controller/EbikeReportRecordController.java new file mode 100644 index 0000000..2c37222 --- /dev/null +++ b/ebike-user/src/main/java/com/cdzy/user/controller/EbikeReportRecordController.java @@ -0,0 +1,36 @@ +package com.cdzy.user.controller; + +import com.cdzy.common.model.response.JsonResult; +import com.cdzy.user.model.dto.EbikeReportRecordDto; +import com.cdzy.user.service.EbikeReportRecordService; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 用户上报记录 控制层 + * + * @author yanglei + * @since 2025-12-23 16:51 + */ + +@RestController +@RequestMapping("/ebikeReportRecord") +public class EbikeReportRecordController { + + @Resource + private EbikeReportRecordService reportRecordService; + + /** + * 保存用户上报记录 + * + * @param reportRecordDto 用户上报记录参数 + */ + @PostMapping("/saveReportRecord") + public JsonResult saveReportRecord(@RequestBody EbikeReportRecordDto reportRecordDto) { + reportRecordService.saveReportRecord(reportRecordDto); + return JsonResult.success(); + } +} diff --git a/ebike-user/src/main/java/com/cdzy/user/controller/EbikeUserController.java b/ebike-user/src/main/java/com/cdzy/user/controller/EbikeUserController.java index 91467c4..3c1e015 100644 --- a/ebike-user/src/main/java/com/cdzy/user/controller/EbikeUserController.java +++ b/ebike-user/src/main/java/com/cdzy/user/controller/EbikeUserController.java @@ -8,6 +8,7 @@ import com.cdzy.user.model.entity.EbikeOrder; import com.cdzy.user.model.entity.EbikeUser; import com.cdzy.user.model.vo.EbikeUserVo; import com.cdzy.user.service.EbikeOrderService; +import com.cdzy.user.service.EbikeUserRealInfoService; import com.cdzy.user.service.EbikeUserService; import com.cdzy.user.utils.RedisUtil; import com.cdzy.user.utils.VerifyUtil; @@ -42,6 +43,9 @@ public class EbikeUserController { @Resource private EbikeOrderService ebikeOrderTransactionService; + @Resource + private EbikeUserRealInfoService ebikeUserRealInfoService; + /** * 用户微信无感登录。 * @@ -97,9 +101,24 @@ public class EbikeUserController { */ @PostMapping("/verifyRealName") public JsonResult verifyRealName(@RequestBody UserValidateDto userValidateDto) { - return verifyUtil.verifyRealName(userValidateDto); + verifyUtil.verifyRealName(userValidateDto); + return JsonResult.success(); } + + /** + * 根据用户id校验用户是否已进行实名认证 + * + * @param userId 用户id + * @return true 已进行实名验证 false 实名认证失败或未进行实名认证 + */ + @GetMapping("/checkUserIsVerify") + public JsonResult checkUserIsVerify(@RequestParam(name = "userId") Long userId) { + boolean result = ebikeUserRealInfoService.checkUserIsVerify(userId); + return JsonResult.success(result); + } + + /** * 注销用户信息。 * diff --git a/ebike-user/src/main/java/com/cdzy/user/mapper/EbikeReportRecordFileMapper.java b/ebike-user/src/main/java/com/cdzy/user/mapper/EbikeReportRecordFileMapper.java new file mode 100644 index 0000000..fead30e --- /dev/null +++ b/ebike-user/src/main/java/com/cdzy/user/mapper/EbikeReportRecordFileMapper.java @@ -0,0 +1,12 @@ +package com.cdzy.user.mapper; + +import com.cdzy.user.model.entity.EbikeReportRecordFile; +import com.mybatisflex.core.BaseMapper; + +/** + * @author yanglei + * @since 2025-12-23 16:50 + */ + +public interface EbikeReportRecordFileMapper extends BaseMapper { +} diff --git a/ebike-user/src/main/java/com/cdzy/user/mapper/EbikeReportRecordMapper.java b/ebike-user/src/main/java/com/cdzy/user/mapper/EbikeReportRecordMapper.java new file mode 100644 index 0000000..009411a --- /dev/null +++ b/ebike-user/src/main/java/com/cdzy/user/mapper/EbikeReportRecordMapper.java @@ -0,0 +1,12 @@ +package com.cdzy.user.mapper; + +import com.cdzy.user.model.entity.EbikeReportRecord; +import com.mybatisflex.core.BaseMapper; + +/** + * @author yanglei + * @since 2025-12-23 16:50 + */ + +public interface EbikeReportRecordMapper extends BaseMapper { +} diff --git a/ebike-user/src/main/java/com/cdzy/user/model/dto/EbikeReportRecordDto.java b/ebike-user/src/main/java/com/cdzy/user/model/dto/EbikeReportRecordDto.java new file mode 100644 index 0000000..44b2462 --- /dev/null +++ b/ebike-user/src/main/java/com/cdzy/user/model/dto/EbikeReportRecordDto.java @@ -0,0 +1,43 @@ +package com.cdzy.user.model.dto; + +import com.cdzy.user.handler.PGpointDeserializer; +import com.cdzy.user.handler.PGpointSerializer; +import com.cdzy.user.handler.PGpointTypeHandler; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.mybatisflex.annotation.Column; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.postgresql.geometric.PGpoint; + +import java.util.List; + +/** + * 用户上报请求参数 + * + * @author yanglei + * @since 2025-12-23 16:55 + */ +@Data +public class EbikeReportRecordDto { + + /** + * 用户id + */ + @NotNull(message = "用户id不能为空") + private Long userId; + + /** + * 骑行起始点 + */ + @Column(typeHandler = PGpointTypeHandler.class) + @JsonSerialize(using = PGpointSerializer.class) + @JsonDeserialize(using = PGpointDeserializer.class) + @NotNull(message = "上报位置") + private PGpoint location; + + /** + * 用户上报文件 + */ + private List recordFiles; +} diff --git a/ebike-user/src/main/java/com/cdzy/user/model/dto/EbikeReportRecordFileDto.java b/ebike-user/src/main/java/com/cdzy/user/model/dto/EbikeReportRecordFileDto.java new file mode 100644 index 0000000..008a49a --- /dev/null +++ b/ebike-user/src/main/java/com/cdzy/user/model/dto/EbikeReportRecordFileDto.java @@ -0,0 +1,29 @@ +package com.cdzy.user.model.dto; + +import lombok.Data; + +/** + * 用户上报文件请求参数 + * + * @author yanglei + * @since 2025-11-18 11:26 + */ + +@Data +public class EbikeReportRecordFileDto { + + /** + * 用户上报文件主键id + */ + private Long recordFileId; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件地址 + */ + private String fileUrl; +} diff --git a/ebike-user/src/main/java/com/cdzy/user/model/entity/EbikeReportRecord.java b/ebike-user/src/main/java/com/cdzy/user/model/entity/EbikeReportRecord.java new file mode 100644 index 0000000..d9bbf42 --- /dev/null +++ b/ebike-user/src/main/java/com/cdzy/user/model/entity/EbikeReportRecord.java @@ -0,0 +1,82 @@ +package com.cdzy.user.model.entity; + +import com.cdzy.user.handler.PGpointDeserializer; +import com.cdzy.user.handler.PGpointSerializer; +import com.cdzy.user.handler.PGpointTypeHandler; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.postgresql.geometric.PGpoint; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author yanglei + * @since 2025-12-23 16:44 + */ + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("ebike_report_record") +public class EbikeReportRecord implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @Id + private Long recordId; + + /** + * 上报位置 + */ + @Column(typeHandler = PGpointTypeHandler.class) + @JsonSerialize(using = PGpointSerializer.class) + @JsonDeserialize(using = PGpointDeserializer.class) + private PGpoint location; + + /** + * 处理状态 0-未处理 1-已处理 + */ + private Integer recordStatus; + + /** + * 创建人 + */ + private Long createBy; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 更新人 + */ + private Long updateBy; + + /** + * 更新时间 + */ + @Column(onUpdateValue = "now()") + private LocalDateTime updateTime; + + /** + * 删除状态(true表示已删除) + */ + private Boolean isDeleted; + +} diff --git a/ebike-user/src/main/java/com/cdzy/user/model/entity/EbikeReportRecordFile.java b/ebike-user/src/main/java/com/cdzy/user/model/entity/EbikeReportRecordFile.java new file mode 100644 index 0000000..5ec74b4 --- /dev/null +++ b/ebike-user/src/main/java/com/cdzy/user/model/entity/EbikeReportRecordFile.java @@ -0,0 +1,76 @@ +package com.cdzy.user.model.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author yanglei + * @since 2025-12-23 16:44 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("ebike_report_record_file") +public class EbikeReportRecordFile implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @Id + private Long recordFileId; + + /** + * 用户退款主键id + */ + private Long recordId; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件地址 + */ + private String fileUrl; + + /** + * 创建人 + */ + private Long createBy; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 更新人 + */ + private Long updateBy; + + /** + * 更新时间 + */ + @Column(onUpdateValue = "now()") + private LocalDateTime updateTime; + + /** + * 删除状态(true表示已删除) + */ + private Boolean isDeleted; +} diff --git a/ebike-user/src/main/java/com/cdzy/user/service/EbikeReportRecordService.java b/ebike-user/src/main/java/com/cdzy/user/service/EbikeReportRecordService.java new file mode 100644 index 0000000..d28d503 --- /dev/null +++ b/ebike-user/src/main/java/com/cdzy/user/service/EbikeReportRecordService.java @@ -0,0 +1,15 @@ +package com.cdzy.user.service; + +import com.cdzy.user.model.dto.EbikeReportRecordDto; +import com.cdzy.user.model.entity.EbikeReportRecord; +import com.mybatisflex.core.service.IService; + +/** + * @author yanglei + * @since 2025-12-23 16:53 + */ + +public interface EbikeReportRecordService extends IService { + + void saveReportRecord(EbikeReportRecordDto reportRecordDto); +} diff --git a/ebike-user/src/main/java/com/cdzy/user/service/EbikeUserRealInfoService.java b/ebike-user/src/main/java/com/cdzy/user/service/EbikeUserRealInfoService.java index b979eb8..5b32585 100644 --- a/ebike-user/src/main/java/com/cdzy/user/service/EbikeUserRealInfoService.java +++ b/ebike-user/src/main/java/com/cdzy/user/service/EbikeUserRealInfoService.java @@ -19,4 +19,12 @@ public interface EbikeUserRealInfoService extends IService { */ EbikeUserRealInfo getRealInfoByUserId(Long userId); + /** + * 校验用户是否已实名认证成功 + * + * @param userId 用户id + * @return true 已实名认证成功 false 实名认证失败 + */ + boolean checkUserIsVerify(Long userId); + } diff --git a/ebike-user/src/main/java/com/cdzy/user/service/impl/EbikeOrderServiceImpl.java b/ebike-user/src/main/java/com/cdzy/user/service/impl/EbikeOrderServiceImpl.java index c5378d3..f2b2908 100644 --- a/ebike-user/src/main/java/com/cdzy/user/service/impl/EbikeOrderServiceImpl.java +++ b/ebike-user/src/main/java/com/cdzy/user/service/impl/EbikeOrderServiceImpl.java @@ -18,6 +18,7 @@ import com.cdzy.user.model.vo.EbikeUserAllOrdersVo; import com.cdzy.user.service.EbikeOrderDetailService; import com.cdzy.user.service.EbikeOrderService; import com.cdzy.user.service.EbikePaymentService; +import com.cdzy.user.service.EbikeUserRealInfoService; import com.cdzy.user.utils.StringUtils; import com.ebike.feign.clients.OperationsFeignClient; import com.ebike.feign.model.dto.FeignEbikeDto; @@ -68,6 +69,9 @@ public class EbikeOrderServiceImpl extends ServiceImpl implements EbikeReportRecordService { + + @Resource + private EbikeReportRecordFileMapper reportRecordFileMapper; + + @Transactional + @Override + public void saveReportRecord(EbikeReportRecordDto reportRecordDto) { + EbikeReportRecord ebikeReportRecord = EbikeReportRecord.builder() + .location(reportRecordDto.getLocation()) + .recordStatus(GlobalConstants.NUMBER_ZERO) + .createBy(reportRecordDto.getUserId()) + .build(); + this.save(ebikeReportRecord); + Long recordId = ebikeReportRecord.getRecordId(); + List recordFiles = reportRecordDto.getRecordFiles(); + if (Objects.nonNull(recordFiles)) { + List fileEntities = recordFiles.stream() + .map(dto -> EbikeReportRecordFile.builder() + .recordId(recordId) + .fileName(dto.getFileName()) + .fileUrl(dto.getFileUrl()) + .createBy(reportRecordDto.getUserId()) + .build()) + .collect(Collectors.toList()); + reportRecordFileMapper.insertBatch(fileEntities); + } + } +} diff --git a/ebike-user/src/main/java/com/cdzy/user/service/impl/EbikeUserRealInfoServiceImpl.java b/ebike-user/src/main/java/com/cdzy/user/service/impl/EbikeUserRealInfoServiceImpl.java index e983bfd..c7ac785 100644 --- a/ebike-user/src/main/java/com/cdzy/user/service/impl/EbikeUserRealInfoServiceImpl.java +++ b/ebike-user/src/main/java/com/cdzy/user/service/impl/EbikeUserRealInfoServiceImpl.java @@ -1,5 +1,6 @@ package com.cdzy.user.service.impl; +import com.cdzy.user.enums.RealNameAttestationStatus; import com.cdzy.user.mapper.EbikeUserRealInfoMapper; import com.cdzy.user.model.entity.EbikeUserRealInfo; import com.cdzy.user.service.EbikeUserRealInfoService; @@ -26,4 +27,15 @@ public class EbikeUserRealInfoServiceImpl extends ServiceImpl verifyRealName(UserValidateDto userValidateDto) { + public void verifyRealName(UserValidateDto userValidateDto) { EbikeUserVo userInfo = ebikeUserService.getUserInfoByUserId(userValidateDto.getUserId()); if (userInfo == null) { - log.error("用户{}不存在", userValidateDto.getUserId()); - return JsonResult.failed("用户不存在"); + throw new EbikeException("用户不存在"); } - // 校验是否已进行验证 Integer realNameStatus = userInfo.getUserRealNameStatus(); if (realNameStatus != null && realNameStatus.equals(RealNameAttestationStatus.CERTIFIED)) { - return JsonResult.failed("用户已实名验证"); + throw new EbikeException("用户已实名验证"); } try { // 1. 加密数据 @@ -177,42 +174,45 @@ public class VerifyUtil { ebikeRealNameVerifyDto.setTimestamp(encryptedTimestamp); ebikeRealNameVerifyDto.setSign(sign); ebikeRealNameVerifyDto.setKey(realNameVerifyConfig.getApiKey()); - - // 2. 验证用户实名 + // 2. 调用第三方实名验证 JsonNode result = httpPost("验证用户实名", REALNAME_VERIFY_URL, ebikeRealNameVerifyDto, null); - log.info("验证用户实名结果:{}", result); + log.info("验证用户实名结果: {}", result); if (result == null) { - log.error("验证用户实名失败"); - return JsonResult.failed("验证用户实名失败"); + throw new EbikeException("验证用户实名失败"); + } + String code = result.has("code") ? result.get("code").asText() : ""; + if (!"10000".equals(code)) { + String message = result.has("message") ? result.get("message").asText() : "未知错误"; + log.error("验证用户实名失败, code: {}, message: {}", code, message); + throw new EbikeException("验证用户实名失败: " + message); + } + // 3. 解密并解析结果 + String data = securityContext.decrypt(result.get("data").asText(), realNameVerifyConfig.getClientPrivateKey()); + JsonNode jsonData = objectMapper.readTree(data); + + if (jsonData.has("result") && "1".equals(jsonData.get("result").asText())) { + // 验证成功直接返回 + updateRealNameInfo(userValidateDto, true); + log.info("验证用户实名成功"); + return; + } else { + // 验证失败 + String failReason = jsonData.has("msg") ? jsonData.get("msg").asText() : "实名验证未通过"; + log.warn("实名验证未通过,原因: {}", failReason); } - if (result.has("code") && "10000".equals(result.get("code").asText())) { - // 3. 解密结果 - String data = securityContext.decrypt(result.get("data").asText(), realNameVerifyConfig.getClientPrivateKey()); - JsonNode jsonData = objectMapper.readTree(data); - if (jsonData.has("result") && "1".equals(jsonData.get("result").asText())) { - // 4. 更新用户实名信息 - updateRealNameInfo(userValidateDto, true); - return JsonResult.success("验证用户实名成功"); - } - } + // 4. 验证失败:更新为未认证 updateRealNameInfo(userValidateDto, false); - String errorCode = result.has("code") ? result.get("code").asText() : "未知错误"; - String errorMessage = result.has("message") ? result.get("message").asText() : "验证失败"; - log.error("验证用户实名失败,{} {}", errorCode, errorMessage); - return JsonResult.failed(errorCode + ", " + errorMessage); + throw new EbikeException("验证用户实名失败"); + } catch (EncryptFailureException e) { - log.error("加密失败", e); - return JsonResult.failed("加密失败"); + throw new EbikeException("加密失败"); } catch (SignFailureException e) { - log.error("签名失败", e); - return JsonResult.failed("签名失败"); + throw new EbikeException("签名失败"); } catch (DecryptFailureException e) { - log.error("结果解密失败", e); - return JsonResult.failed("结果解密失败"); + throw new EbikeException("结果解密失败"); } catch (JsonProcessingException e) { - log.error("JSON解析失败", e); - return JsonResult.failed("数据解析失败"); + throw new EbikeException("数据解析失败"); } } @@ -277,7 +277,7 @@ public class VerifyUtil { private JsonNode httpPost(String func_, String url, EbikeRealNameVerifyDto dto, Map body) { StringBuilder queryString = new StringBuilder(); appendParam(queryString, "name", dto.getName()); - appendParam(queryString, "idCard", dto.getIdCard()); + appendParam(queryString, "idcard", dto.getIdCard()); appendParam(queryString, "timestamp", dto.getTimestamp()); appendParam(queryString, "sign", dto.getSign()); appendParam(queryString, "key", dto.getKey()); diff --git a/ebike-user/src/main/resources/application-dev.yml b/ebike-user/src/main/resources/application-dev.yml index 23507fe..aae83cf 100644 --- a/ebike-user/src/main/resources/application-dev.yml +++ b/ebike-user/src/main/resources/application-dev.yml @@ -74,9 +74,12 @@ wechat: #数据宝 real-name: - api-key: 00fb13c55a660c64299d32aa041d77ad - client-private-key: c437d793ecc0b35845c30aeb7c330baca69dcfcf2a69f6cddccf978a2023ca1f - server-public-key: 03b7affa6dd528711e3d9a853900a712f98bc27678b68a4af50e4381b730de96e5 + api-key: 086ba8e74bd22b814af36f12371f8f3e + #客户端私钥 + client-private-key: cc1ed364d4c05b9ce0de5c690484c301e00452c1f183f93fa43e5b0ba6a76c99 + #服务端公钥 + server-public-key: 03a21563bf3d2b43cfd519918a0138ac6cfde1ff3b0e4a7a31edb602e9537390a7 + management: endpoints: