xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpCruiseCheckInRecord.java
New file @@ -0,0 +1,68 @@ package com.xiaopeng.api.model.maintenance; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.xiaopeng.common.core.web.domain.BaseModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.time.LocalDateTime; /** * 巡游打卡记录 */ @Data @TableName("xp_cruise_check_in_record") public class XpCruiseCheckInRecord extends BaseModel { /** * 主键 */ @TableId(value = "id", type = IdType.NONE) private Long id; /** * 运维人员id */ @TableField("operations_user_id") private Long operationsUserId; /** * 打卡点位id */ @ApiModelProperty("打卡点位id") @TableField("check_location_id") private Long checkLocationId; /** * 巡游打卡规则id */ @TableField("cruise_check_in_rule_id") private Integer cruiseCheckInRuleId; /** * 打卡时间 */ @TableField("check_in_time") private LocalDateTime checkInTime; /** * 打卡结果(1=正常打卡,2=迟到打卡) */ @TableField("check_in_result") private Integer checkInResult; /** * 现场情况(1=正常,2=拥堵) */ @ApiModelProperty("现场情况(1=正常,2=拥堵)") @TableField("field_situation") private Integer fieldSituation; /** * 现场照片JSON数组 */ @ApiModelProperty("现场照片JSON数组") @TableField("scene_photo") private String scenePhoto; /** * 现场情况说明 */ @ApiModelProperty("现场情况说明") @TableField("scene_description") private String sceneDescription; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpCruiseCheckInRule.java
New file @@ -0,0 +1,43 @@ package com.xiaopeng.api.model.maintenance; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.xiaopeng.common.core.web.domain.BaseModel; import lombok.Data; import java.time.LocalDateTime; /** * 巡游打卡规则 */ @Data @TableName("xp_cruise_check_in_rule") public class XpCruiseCheckInRule extends BaseModel { /** * 主键 */ @TableId(value = "id", type = IdType.AUTO) private Integer id; /** * 规则名称 */ @TableField("name") private String name; /** * 任务开始时间 */ @TableField("start_time") private LocalDateTime startTime; /** * 任务结束时间 */ @TableField("end_time") private LocalDateTime endTime; /** * 循环方式(0=不循环,1=每天循环) */ @TableField("cyclic_mode") private Integer cyclicMode; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpCruiseCheckInRuleLocation.java
New file @@ -0,0 +1,39 @@ package com.xiaopeng.api.model.maintenance; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; /** * 巡游打卡规则和打卡点位关系实体 */ @Data @TableName("xp_cruise_check_in_rule_location") public class XpCruiseCheckInRuleLocation { /** * 巡游打卡规则id */ @TableField("cruise_check_in_rule_id") private Integer cruiseCheckInRuleId; /** * 打卡点位id */ @TableField("check_location_id") private Long checkLocationId; /** * 打卡开始时段 */ @TableField("start_time") private String startTime; /** * 打卡结束时段 */ @TableField("end_time") private String endTime; /** * 打卡顺序 */ @TableField("sort") private Integer sort; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpCruiseCheckInRuleOperationsUser.java
New file @@ -0,0 +1,24 @@ package com.xiaopeng.api.model.maintenance; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; /** * 巡游打卡规则和运维人员关系实体 */ @Data @TableName("xp_cruise_check_in_rule_operations_user") public class XpCruiseCheckInRuleOperationsUser { /** * 巡游打卡规则id */ @TableField("cruise_check_in_rule_id") private Integer cruiseCheckInRuleId; /** * 运维人员id */ @TableField("operations_user_id") private Long operationsUserId; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpLoginAgreement.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.xiaopeng.common.core.web.domain.BaseModel; import lombok.Data; @@ -10,6 +11,7 @@ * 登录协议 */ @Data @TableName("xp_login_agreement") public class XpLoginAgreement extends BaseModel { /** * 数据id xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpPoint.java
@@ -26,7 +26,7 @@ @Accessors(chain = true) @TableName("xp_point") @ApiModel(value="XpPoint对象", description="点位管理") public class XpPoint extends BaseModel { public class XpPoint extends c { private static final long serialVersionUID = 1L; xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpPointSituationReport.java
New file @@ -0,0 +1,57 @@ package com.xiaopeng.api.model.operation; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.xiaopeng.common.core.web.domain.BaseModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.time.LocalDateTime; /** * 点位现场情况上报 */ @Data public class XpPointSituationReport extends BaseModel { /** * 主键 */ @TableId(value = "id", type = IdType.AUTO) private Integer id; /** * 点位id */ @ApiModelProperty("点位id") @TableField("point_id") private Integer pointId; /** * 现场情况(1=正常,2=异常) */ @ApiModelProperty("现场情况(1=正常,2=异常)") @TableField("field_situation") private String fieldSituation; /** * 现场照片JSON数组 */ @ApiModelProperty("现场照片JSON数组") @TableField("scene_photo") private String scenePhoto; /** * 现场情况说明 */ @ApiModelProperty("现场情况说明") @TableField("scene_description") private String sceneDescription; /** * 上报运维id */ @TableField("operations_user_id") private Long operationsUserId; /** * 现场情况上报时间 */ @TableField("reporting_time") private LocalDateTime reportingTime; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/operation/PointListQuery.java
@@ -25,4 +25,8 @@ @ApiModelProperty(value = "点位状态(多选) 1待测试 2测试中 3测试不通过 4可运营 5待生效 6启用中 7已停用 8已失效") private List<Integer> operationStatusList; @ApiModelProperty("当前定位经度") private Double longitude; @ApiModelProperty("当前定位纬度") private Double latitude; } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/I18nKeyConstant.java
@@ -13,4 +13,6 @@ String TASK_SAVE_ERROR = "task.save.error"; String TASK_VEHICLE_NOT_EXIST = "task.vehicle.not.exist"; String ACCIDENT_TYPE_NOT_EXIST = "accident.type.not.exist"; String CHECK_IN_LOCATION_DOES_NOT_EXIST = "check.in.location.does.not.exist"; String CANNOT_REPEAT_CLOCKING_IN = "cannot.repeat.clocking.in"; } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpCruiseCheckInRuleController.java
New file @@ -0,0 +1,92 @@ package com.xiaopeng.maintenance.controller; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRecord; import com.xiaopeng.api.vo.account.LoginOperationUser; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.security.service.TokenService; import com.xiaopeng.maintenance.model.vo.AppXpCruiseCheckInLocationVo; import com.xiaopeng.maintenance.model.vo.AppXpCruiseCheckInRuleVo; import com.xiaopeng.maintenance.model.vo.CheckInMessageVo; import com.xiaopeng.maintenance.model.vo.RealTimePositionVo; import com.xiaopeng.maintenance.service.IXpCruiseCheckInRuleService; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; /** * 巡游打卡规则 */ @RestController @RequestMapping("") public class XpCruiseCheckInRuleController { @Resource public IXpCruiseCheckInRuleService xpCruiseCheckInRuleService; @Resource private TokenService tokenService; @ApiOperation(value = "获取个人中心巡游打卡任务", tags = {"运维APP-个人中心"}) @GetMapping("/maintenance-app/api/v1/cruiseCheckInRule/getMyXpCruiseCheckInRule") public R<AppXpCruiseCheckInRuleVo> getMyXpCruiseCheckInRule() { LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser(); AppXpCruiseCheckInRuleVo myXpCruiseCheckInRule = xpCruiseCheckInRuleService.getMyXpCruiseCheckInRule(loginOperationUser.getId()); return R.ok(myXpCruiseCheckInRule); } @ApiOperation(value = "获取巡游打卡定位列表", tags = {"运维APP-个人中心"}) @ApiImplicitParams({ @ApiImplicitParam(value = "任务id", name = "id", required = true, dataType = "Integer") }) @GetMapping("/maintenance-app/api/v1/cruiseCheckInRule/getAppXpCruiseCheckInLocation/{id}") public R<List<AppXpCruiseCheckInLocationVo>> getAppXpCruiseCheckInLocation(@PathVariable("id") Integer id){ LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser(); List<AppXpCruiseCheckInLocationVo> appXpCruiseCheckInLocation = xpCruiseCheckInRuleService.getAppXpCruiseCheckInLocation(id, loginOperationUser.getId()); return R.ok(appXpCruiseCheckInLocation); } @ApiOperation(value = "巡游打卡操作", tags = {"运维APP-个人中心"}) @PostMapping("/maintenance-app/api/v1/cruiseCheckInRule/saveCruiseCheckInRecord") public R<?> saveCruiseCheckInRecord(@RequestBody XpCruiseCheckInRecord dto){ LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser(); dto.setOperationsUserId(loginOperationUser.getId()); xpCruiseCheckInRuleService.saveCruiseCheckInRecord(dto); return R.ok(); } @ApiOperation(value = "巡游打卡5秒钟轮询上传实时位置", tags = {"运维APP-个人中心"}) @PostMapping("/maintenance-app/api/v1/cruiseCheckInRule/uploadRealTimePosition") public R<CheckInMessageVo> uploadRealTimePosition(@RequestBody RealTimePositionVo dto){ LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser(); CheckInMessageVo checkInMessageVo = xpCruiseCheckInRuleService.uploadRealTimePosition(dto, loginOperationUser.getId()); return R.ok(checkInMessageVo); } @ApiOperation(value = "获取打卡结果详情", tags = {"运维APP-个人中心"}) @ApiImplicitParams({ @ApiImplicitParam(value = "任务id", name = "id", required = true, dataType = "Integer"), @ApiImplicitParam(value = "打卡点位id", name = "locationId", required = true, dataType = "Long") }) @GetMapping("/maintenance-app/api/v1/cruiseCheckInRule/getCruiseCheckInRecordInfo/{id}/{locationId}") public R<XpCruiseCheckInRecord> getCruiseCheckInRecordInfo(@PathVariable("id") Integer id, @PathVariable("locationId") Long locationId) { LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser(); XpCruiseCheckInRecord cruiseCheckInRecordInfo = xpCruiseCheckInRuleService.getCruiseCheckInRecordInfo(id, locationId, loginOperationUser.getId()); return R.ok(cruiseCheckInRecordInfo); } } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/mapper/XpCruiseCheckInRecordMapper.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.maintenance.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRecord; public interface XpCruiseCheckInRecordMapper extends BaseMapper<XpCruiseCheckInRecord> { } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/mapper/XpCruiseCheckInRuleLocationMapper.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.maintenance.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRuleLocation; public interface XpCruiseCheckInRuleLocationMapper extends BaseMapper<XpCruiseCheckInRuleLocation> { } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/mapper/XpCruiseCheckInRuleMapper.java
New file @@ -0,0 +1,10 @@ package com.xiaopeng.maintenance.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRule; import com.xiaopeng.maintenance.model.vo.AppXpCruiseCheckInRuleVo; import org.apache.ibatis.annotations.Param; public interface XpCruiseCheckInRuleMapper extends BaseMapper<XpCruiseCheckInRule> { } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/model/vo/AppXpCruiseCheckInLocationVo.java
New file @@ -0,0 +1,28 @@ package com.xiaopeng.maintenance.model.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; @Data @ApiModel public class AppXpCruiseCheckInLocationVo { @ApiModelProperty("点位id") private Long locationId; @ApiModelProperty("打卡时限") private String time; @ApiModelProperty("打卡时间") private String checkInTime; @ApiModelProperty("是否已打卡(0=否,1=是)") private Integer checkIn; @ApiModelProperty("打卡结果(1=正常打卡,2=超时打卡)") private Integer checkInResult; @ApiModelProperty("经度") private BigDecimal lon; @ApiModelProperty("纬度") private BigDecimal lat; @ApiModelProperty("地址") private String address; } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/model/vo/AppXpCruiseCheckInRuleVo.java
New file @@ -0,0 +1,20 @@ package com.xiaopeng.maintenance.model.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel public class AppXpCruiseCheckInRuleVo { @ApiModelProperty("任务id") private Integer id; @ApiModelProperty("巡游打卡任务时间") private String cruiseCheckInTaskTime; @ApiModelProperty("打卡点位总数") private Long checkInPointCount; @ApiModelProperty("打卡点位完成数") private Long checkInPointFinishCount; @ApiModelProperty("打卡点位未完成数") private Long checkInPointUnFinishCount; } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/model/vo/CheckInMessageVo.java
New file @@ -0,0 +1,16 @@ package com.xiaopeng.maintenance.model.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel public class CheckInMessageVo { @ApiModelProperty("消息类型(1=即将超时提醒,2=到达打卡点提醒)") private Integer messageType; @ApiModelProperty("巡游打卡点位id") private Long checkLocationId; @ApiModelProperty("提示内容") private String message; } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/model/vo/CruiseCheckInRecordInfoVo.java
New file @@ -0,0 +1,17 @@ package com.xiaopeng.maintenance.model.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.time.LocalDateTime; @Data @ApiModel public class CruiseCheckInRecordInfoVo { @ApiModelProperty("巡游打卡任务id") private Integer id; @ApiModelProperty("巡游打卡点位id") private Long locationId; } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/model/vo/RealTimePositionVo.java
New file @@ -0,0 +1,16 @@ package com.xiaopeng.maintenance.model.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel public class RealTimePositionVo { @ApiModelProperty("巡游打卡id") private Integer id; @ApiModelProperty("纬度") private Double latitude; @ApiModelProperty("经度") private Double longitude; } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/IXpCruiseCheckInRecordService.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.maintenance.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRecord; public interface IXpCruiseCheckInRecordService extends IService<XpCruiseCheckInRecord> { } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/IXpCruiseCheckInRuleLocationService.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.maintenance.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRuleLocation; public interface IXpCruiseCheckInRuleLocationService extends IService<XpCruiseCheckInRuleLocation> { } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/IXpCruiseCheckInRuleService.java
New file @@ -0,0 +1,58 @@ package com.xiaopeng.maintenance.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRecord; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRule; import com.xiaopeng.maintenance.model.vo.AppXpCruiseCheckInLocationVo; import com.xiaopeng.maintenance.model.vo.AppXpCruiseCheckInRuleVo; import com.xiaopeng.maintenance.model.vo.CheckInMessageVo; import com.xiaopeng.maintenance.model.vo.RealTimePositionVo; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; public interface IXpCruiseCheckInRuleService extends IService<XpCruiseCheckInRule> { /** * 获取运维人员当日巡游打卡任务数据-APP个人中心页 * @param uid * @return */ AppXpCruiseCheckInRuleVo getMyXpCruiseCheckInRule(Long uid); /** * 获取运维人员个人中心的巡游打卡点位列表 * @param ruleId * @param uid * @return */ List<AppXpCruiseCheckInLocationVo> getAppXpCruiseCheckInLocation(Integer ruleId, Long uid); /** * 运维人员巡游打卡操作 * @param dto */ void saveCruiseCheckInRecord(XpCruiseCheckInRecord dto); /** * 运维端实时上传位置信息,返回提醒消息 * @param dto * @return */ CheckInMessageVo uploadRealTimePosition(RealTimePositionVo dto, Long uid); /** * 获取巡游打卡详情 * @param ruleId * @param locationId * @param uid * @return */ XpCruiseCheckInRecord getCruiseCheckInRecordInfo(Integer ruleId, Long locationId, Long uid); } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpCruiseCheckInRecordServiceImpl.java
New file @@ -0,0 +1,11 @@ package com.xiaopeng.maintenance.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRecord; import com.xiaopeng.maintenance.mapper.XpCruiseCheckInRecordMapper; import com.xiaopeng.maintenance.service.IXpCruiseCheckInRecordService; import org.springframework.stereotype.Service; @Service public class XpCruiseCheckInRecordServiceImpl extends ServiceImpl<XpCruiseCheckInRecordMapper, XpCruiseCheckInRecord> implements IXpCruiseCheckInRecordService { } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpCruiseCheckInRuleLocationServiceImpl.java
New file @@ -0,0 +1,12 @@ package com.xiaopeng.maintenance.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRuleLocation; import com.xiaopeng.maintenance.mapper.XpCruiseCheckInRuleLocationMapper; import com.xiaopeng.maintenance.service.IXpCruiseCheckInRuleLocationService; import org.springframework.stereotype.Service; @Service public class XpCruiseCheckInRuleLocationServiceImpl extends ServiceImpl<XpCruiseCheckInRuleLocationMapper, XpCruiseCheckInRuleLocation> implements IXpCruiseCheckInRuleLocationService { } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpCruiseCheckInRuleServiceImpl.java
New file @@ -0,0 +1,237 @@ package com.xiaopeng.maintenance.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.model.maintenance.XpCheckLocation; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRecord; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRule; import com.xiaopeng.api.model.maintenance.XpCruiseCheckInRuleLocation; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.GeodesyUtil; import com.xiaopeng.maintenance.constant.I18nKeyConstant; import com.xiaopeng.maintenance.mapper.XpCruiseCheckInRuleMapper; import com.xiaopeng.maintenance.model.vo.AppXpCruiseCheckInLocationVo; import com.xiaopeng.maintenance.model.vo.AppXpCruiseCheckInRuleVo; import com.xiaopeng.maintenance.model.vo.CheckInMessageVo; import com.xiaopeng.maintenance.model.vo.RealTimePositionVo; import com.xiaopeng.maintenance.service.IXpCheckLocationService; import com.xiaopeng.maintenance.service.IXpCruiseCheckInRecordService; import com.xiaopeng.maintenance.service.IXpCruiseCheckInRuleLocationService; import com.xiaopeng.maintenance.service.IXpCruiseCheckInRuleService; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service public class XpCruiseCheckInRuleServiceImpl extends ServiceImpl<XpCruiseCheckInRuleMapper, XpCruiseCheckInRule> implements IXpCruiseCheckInRuleService { @Resource private IXpCruiseCheckInRecordService xpCruiseCheckInRecordService; @Resource private IXpCruiseCheckInRuleLocationService xpCruiseCheckInRuleLocationService; @Resource private IXpCheckLocationService xpCheckLocationService; @Override public AppXpCruiseCheckInRuleVo getMyXpCruiseCheckInRule(Long uid) { List<XpCruiseCheckInRule> list = this.list(new LambdaQueryWrapper<XpCruiseCheckInRule>().eq(XpCruiseCheckInRule::getDeleted, 0) .last(" and (now() BETWEEN start_time and end_time or a.cyclic_mode = 1)")); if(list.isEmpty()){ return null; } XpCruiseCheckInRule xpCruiseCheckInRule = list.get(0); AppXpCruiseCheckInRuleVo vo = new AppXpCruiseCheckInRuleVo(); vo.setId(xpCruiseCheckInRule.getId()); vo.setCruiseCheckInTaskTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + xpCruiseCheckInRule.getStartTime().format(DateTimeFormatter.ofPattern("HH:mm")) + "~" + xpCruiseCheckInRule.getEndTime().format(DateTimeFormatter.ofPattern("HH:mm"))); long count1 = xpCruiseCheckInRuleLocationService.count(new LambdaQueryWrapper<XpCruiseCheckInRuleLocation>() .eq(XpCruiseCheckInRuleLocation::getCruiseCheckInRuleId, xpCruiseCheckInRule.getId())); long count = xpCruiseCheckInRecordService.count(new LambdaQueryWrapper<XpCruiseCheckInRecord>() .eq(XpCruiseCheckInRecord::getCruiseCheckInRuleId, xpCruiseCheckInRule.getId()) .eq(XpCruiseCheckInRecord::getDeleted, 0).eq(XpCruiseCheckInRecord::getOperationsUserId, uid)); vo.setCheckInPointCount(count1); vo.setCheckInPointFinishCount(count); vo.setCheckInPointUnFinishCount(count1 - count); return vo; } /** * 获取APP端签到规则位置信息 * @param ruleId * @param uid * @return */ @Override public List<AppXpCruiseCheckInLocationVo> getAppXpCruiseCheckInLocation(Integer ruleId, Long uid) { //查询巡游打卡规则和点位关系数据 List<XpCruiseCheckInRuleLocation> list = xpCruiseCheckInRuleLocationService.list(new LambdaQueryWrapper<XpCruiseCheckInRuleLocation>() .eq(XpCruiseCheckInRuleLocation::getCruiseCheckInRuleId, ruleId).orderByAsc(XpCruiseCheckInRuleLocation::getSort)); //查询打卡点位数据 List<XpCheckLocation> xpCheckLocations = xpCheckLocationService.listByIds(list.stream().map(XpCruiseCheckInRuleLocation::getCheckLocationId).collect(Collectors.toList())); List<AppXpCruiseCheckInLocationVo> appXpCruiseCheckInLocationVos = new ArrayList<>(); //获取运维人员打卡记录 List<XpCruiseCheckInRecord> list1 = xpCruiseCheckInRecordService.list(new LambdaQueryWrapper<XpCruiseCheckInRecord>() .eq(XpCruiseCheckInRecord::getDeleted, 0) .eq(XpCruiseCheckInRecord::getCruiseCheckInRuleId, ruleId) .eq(XpCruiseCheckInRecord::getOperationsUserId, uid) .last(" and DATE_FORMAT(check_in_time, '%Y-%m-%d') = DATE_FORMAT(NOW(), '%Y-%m-%d")); //构建返回结果 for (XpCruiseCheckInRuleLocation xpCruiseCheckInRuleLocation : list) { XpCruiseCheckInRecord xpCruiseCheckInRecord = list1.stream().filter(x -> x.getCheckLocationId().equals(xpCruiseCheckInRuleLocation.getCheckLocationId())).findFirst().orElse(null); XpCheckLocation xpCheckLocation = xpCheckLocations.stream().filter(x -> x.getId().equals(xpCruiseCheckInRuleLocation.getCheckLocationId())).findFirst().orElse(null); AppXpCruiseCheckInLocationVo vo = new AppXpCruiseCheckInLocationVo(); vo.setLocationId(xpCruiseCheckInRuleLocation.getCheckLocationId()); vo.setTime(xpCruiseCheckInRuleLocation.getStartTime() + "-" + xpCruiseCheckInRuleLocation.getEndTime()); vo.setCheckIn(0); if(null != xpCruiseCheckInRecord){ vo.setCheckInTime(xpCruiseCheckInRecord.getCheckInTime().format(DateTimeFormatter.ofPattern("HH:mm:ss"))); vo.setCheckIn(1); vo.setCheckInResult(xpCruiseCheckInRecord.getCheckInResult()); } vo.setLon(xpCheckLocation.getLocationLon()); vo.setLat(xpCheckLocation.getLocationLat()); vo.setAddress(xpCheckLocation.getLocationAddress()); appXpCruiseCheckInLocationVos.add(vo); } return appXpCruiseCheckInLocationVos; } /** * 运维人员巡游打卡操作 * @param dto */ @Override public void saveCruiseCheckInRecord(XpCruiseCheckInRecord dto) { Long checkLocationId = dto.getCheckLocationId(); XpCruiseCheckInRuleLocation one = xpCruiseCheckInRuleLocationService.getOne(new LambdaQueryWrapper<XpCruiseCheckInRuleLocation>() .eq(XpCruiseCheckInRuleLocation::getCheckLocationId, checkLocationId)); if(null == one){ throw new ServiceException("打卡点位不存在", I18nKeyConstant.CHECK_IN_LOCATION_DOES_NOT_EXIST); } XpCruiseCheckInRecord cruiseCheckInRecord = xpCruiseCheckInRecordService.getOne(new LambdaQueryWrapper<XpCruiseCheckInRecord>() .eq(XpCruiseCheckInRecord::getCruiseCheckInRuleId, one.getCruiseCheckInRuleId()) .eq(XpCruiseCheckInRecord::getDeleted, 0) .eq(XpCruiseCheckInRecord::getCheckLocationId, checkLocationId) .eq(XpCruiseCheckInRecord::getOperationsUserId, dto.getOperationsUserId()) .last(" and DATE_FORMAT(check_in_time, '%Y-%m-%d') = DATE_FORMAT(NOW(), '%Y-%m-%d')")); if(null != cruiseCheckInRecord){ throw new ServiceException("不能重复打卡", I18nKeyConstant.CANNOT_REPEAT_CLOCKING_IN); } dto.setCruiseCheckInRuleId(one.getCruiseCheckInRuleId()); dto.setCheckInTime(LocalDateTime.now()); dto.setCheckInResult(1); //判断当前打卡时间是否超过限定时间 Integer endTime = Integer.valueOf(one.getEndTime().replace(":", "")); Integer nowTime = Integer.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmm"))); if(nowTime > endTime){ dto.setCheckInResult(2); } dto.setDeleted(false); xpCruiseCheckInRecordService.save(dto); } /** * 运维端实时上传位置信息,返回提醒消息 * @param dto * @return */ @Override public CheckInMessageVo uploadRealTimePosition(RealTimePositionVo dto, Long uid) { List<XpCruiseCheckInRuleLocation> list = xpCruiseCheckInRuleLocationService.list(new LambdaQueryWrapper<XpCruiseCheckInRuleLocation>() .eq(XpCruiseCheckInRuleLocation::getCruiseCheckInRuleId, dto.getId()) .orderByAsc(XpCruiseCheckInRuleLocation::getSort)); if(list.isEmpty()){ return null; } //查找即将需要到达的打卡点位 XpCruiseCheckInRecord cruiseCheckInRecord = xpCruiseCheckInRecordService.getOne(new LambdaQueryWrapper<XpCruiseCheckInRecord>() .eq(XpCruiseCheckInRecord::getCruiseCheckInRuleId, dto.getId()) .eq(XpCruiseCheckInRecord::getDeleted, 0) .eq(XpCruiseCheckInRecord::getOperationsUserId, uid) .last(" and DATE_FORMAT(check_in_time, '%Y-%m-%d') = DATE_FORMAT(NOW(), '%Y-%m-%d') order by check_in_time desc limit 1")); XpCruiseCheckInRuleLocation cruiseCheckInRuleLocation = null; //没有打卡的情况,用第一个打卡点位 if(null == cruiseCheckInRecord){ cruiseCheckInRuleLocation = list.get(0); }else{ Long checkLocationId = cruiseCheckInRecord.getCheckLocationId(); for (int i = 0; i < list.size(); i++) { Long checkLocationId1 = list.get(i).getCheckLocationId(); if(checkLocationId.equals(checkLocationId1) && i < list.size() - 1){ cruiseCheckInRuleLocation = list.get(i + 1); break; } } } //没有需要打卡的点位,则返回空数据 if(null == cruiseCheckInRuleLocation){ return null; } //先判断当前定位是否到达打卡点位附近,在范围内则返回打卡消息 XpCheckLocation xpCheckLocation = xpCheckLocationService.getById(cruiseCheckInRuleLocation.getCheckLocationId()); if(null == xpCheckLocation){ return null; } CheckInMessageVo vo = new CheckInMessageVo(); Map<String, Double> distance = GeodesyUtil.getDistance(xpCheckLocation.getLocationLon() + "," + xpCheckLocation.getLocationLat(), dto.getLongitude() + "," + dto.getLatitude()); if(xpCheckLocation.getLocationRange().compareTo(new BigDecimal(distance.get("WGS84"))) >= 0){ vo.setMessageType(1); vo.setCheckLocationId(cruiseCheckInRuleLocation.getCheckLocationId()); return vo; } //判断时间小于10分钟首次触发和小于3分钟再次触发 LocalDateTime now = LocalDateTime.now(); LocalDateTime endTime = now.withHour(Integer.parseInt(cruiseCheckInRuleLocation.getEndTime().split(":")[0])) .withMinute(Integer.parseInt(cruiseCheckInRuleLocation.getEndTime().split(":")[1])) .withSecond(0); long time = endTime.toEpochSecond(ZoneOffset.of("+8")) - now.toEpochSecond(ZoneOffset.of("+8")); if((time <= 10 * 60 && time > 10 * 50) || (time <= 3 * 60 && time > 3 * 50)){ vo.setMessageType(2); vo.setCheckLocationId(cruiseCheckInRuleLocation.getCheckLocationId()); vo.setMessage(time > 10 * 50 ? "距离打卡超时还有10分钟,请尽快前往打卡点" : "距离打卡超时还有3分钟,请尽快前往打卡点"); return vo; } return null; } /** * 获取巡游打卡详情 * @param ruleId * @param locationId * @param uid * @return */ @Override public XpCruiseCheckInRecord getCruiseCheckInRecordInfo(Integer ruleId, Long locationId, Long uid) { return xpCruiseCheckInRecordService.getOne(new LambdaQueryWrapper<XpCruiseCheckInRecord>() .eq(XpCruiseCheckInRecord::getCruiseCheckInRuleId, ruleId) .eq(XpCruiseCheckInRecord::getCheckLocationId, locationId) .eq(XpCruiseCheckInRecord::getDeleted, 0) .eq(XpCruiseCheckInRecord::getOperationsUserId, uid) .last(" and DATE_FORMAT(check_in_time, '%Y-%m-%d') = DATE_FORMAT(NOW(), '%Y-%m-%d')")); } } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/utils/GeodesyUtil.java
New file @@ -0,0 +1,71 @@ package com.xiaopeng.maintenance.utils; import org.gavaghan.geodesy.Ellipsoid; import org.gavaghan.geodesy.GeodeticCalculator; import org.gavaghan.geodesy.GeodeticCurve; import org.gavaghan.geodesy.GlobalCoordinates; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; /** * 计算两个金纬度坐标之间的直线距离 */ @Component public class GeodesyUtil { /** * 获取直线距离 * @param fromLonLat * @param toLonLat * @return */ public Map<String, Double> getDistance(String fromLonLat, String toLonLat){ String[] from = fromLonLat.split(","); String[] to = toLonLat.split(","); GlobalCoordinates source = new GlobalCoordinates(Double.valueOf(from[1]), Double.valueOf(from[0])); GlobalCoordinates target = new GlobalCoordinates(Double.valueOf(to[1]), Double.valueOf(to[0])); double Sphere = getDistanceMeter(source, target, Ellipsoid.Sphere); double WGS84 = getDistanceMeter(source, target, Ellipsoid.WGS84); double GRS80 = getDistanceMeter(source, target, Ellipsoid.GRS80); double GRS67 = getDistanceMeter(source, target, Ellipsoid.GRS67); double ANS = getDistanceMeter(source, target, Ellipsoid.ANS); double WGS72 = getDistanceMeter(source, target, Ellipsoid.WGS72); double Clarke1858 = getDistanceMeter(source, target, Ellipsoid.Clarke1858); double Clarke1880 = getDistanceMeter(source, target, Ellipsoid.Clarke1880); // System.out.println("Sphere坐标系计算结果:"+Sphere + "米"); // System.out.println("WGS84坐标系计算结果:"+WGS84 + "米"); // System.out.println("GRS80坐标系计算结果:"+GRS80 + "米"); // System.out.println("GRS67坐标系计算结果:"+GRS67 + "米"); // System.out.println("ANS坐标系计算结果:"+ANS + "米"); // System.out.println("WGS72坐标系计算结果:"+WGS72 + "米"); // System.out.println("Clarke1858坐标系计算结果:"+Clarke1858 + "米"); // System.out.println("Clarke1880坐标系计算结果:"+Clarke1880 + "米"); Map<String, Double> map = new HashMap<>(); map.put("Sphere", Sphere); map.put("WGS84", WGS84); map.put("GRS80", GRS80); map.put("GRS67", GRS67); map.put("ANS", ANS); map.put("WGS72", WGS72); map.put("Clarke1858", Clarke1858); map.put("Clarke1880", Clarke1880); return map; } private double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid){ //创建GeodeticCalculator,调用计算方法,传入坐标系、经纬度用于计算距离 GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo); return geoCurve.getEllipsoidalDistance(); } public static void main(String[] ages){ GeodesyUtil geodesyUtil = new GeodesyUtil(); geodesyUtil.getDistance("115.481028,39.989643", "114.465302,40.004717"); } } xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties
@@ -5,4 +5,6 @@ repair.money.too.long=维修费用不能超过10字符 task.save.error=获取车辆实时定位信息失败,请稍后重试 task.vehicle.not.exist=上报失败,未获取到车辆信息 accident.type.not.exist=事故类型不存在 accident.type.not.exist=事故类型不存在 check.in.location.does.not.exist="打卡点位不存在" cannot.repeat.clocking.in="不能重复打卡" xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties
@@ -7,3 +7,5 @@ task.vehicle.not.exist=The report failed and no vehicle information was obtained accident.type.not.exist=The accident type does not exist. task.rule.not.config=The vehicle accident task allocation rules have not been configured check.in.location.does.not.exist="The check-in location does not exist." cannot.repeat.clocking.in="Cannot repeat clocking in" xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -6,4 +6,6 @@ task.save.error=获取车辆实时定位信息失败,请稍后重试 task.vehicle.not.exist=上报失败,未获取到车辆信息 accident.type.not.exist=事故类型不存在 task.rule.not.config=未配置车辆事故任务分配规则 task.rule.not.config=未配置车辆事故任务分配规则 check.in.location.does.not.exist="打卡点位不存在" cannot.repeat.clocking.in="不能重复打卡" xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpCruiseCheckInRecordMapper.xml
New file @@ -0,0 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.maintenance.mapper.XpCruiseCheckInRecordMapper"> </mapper> xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpCruiseCheckInRuleMapper.xml
New file @@ -0,0 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.maintenance.mapper.XpCruiseCheckInRuleMapper"> </mapper> xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/IndexController.java
@@ -35,22 +35,24 @@ LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser(); query.setOperationId(loginOperationUser.getId()); // 获取任务记录 R<List<XpPoint>> pageInfo= pointClient.pointMap(query); R<List<XpPoint>> pageInfo = pointClient.pointMap(query); return pageInfo; } @ApiOperation(value = "点位管理列表", tags = {"运维APP-站点导航"}) @PostMapping("/maintenance-app/api/v1/map/list") public R<List<XpPoint>> list(@RequestBody PointListQuery query) { return pointClient.list( query); return pointClient.list(query); } @ApiOperation(value = "点位详情") @GetMapping("/api/v1/pointDetail") public R<XpPoint> pointDetail(@RequestParam(value = "点位id", required = true)Long id) { public R<XpPoint> pointDetail(@RequestParam(value = "点位id", required = true) Long id) { return pointClient.queryById(id); } } xp-robotaxi-map-boot/xp-robotaxi-map-boot.iml
New file @@ -0,0 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <module version="4"> <component name="AdditionalModuleElements"> <content url="file://$MODULE_DIR$" dumb="true"> <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" /> </content> </component> </module> xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPointSituationReportController.java
New file @@ -0,0 +1,44 @@ package com.xiaopeng.operation.controller; import com.xiaopeng.api.model.operation.XpPointSituationReport; import com.xiaopeng.api.vo.account.LoginOperationUser; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.security.service.TokenService; import com.xiaopeng.operation.service.IXpPointSituationReportService; import com.xiaopeng.operation.vo.XpAgreementVo; import io.swagger.annotations.ApiOperation; 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; import javax.annotation.Resource; import java.time.LocalDateTime; @RestController @RequestMapping("") public class XpPointSituationReportController { @Resource private IXpPointSituationReportService xpPointSituationReportService; @Resource private TokenService tokenService; @ApiOperation(value = "现场情况上报", tags = {"运维APP-站点管理"}, response = XpPointSituationReport.class) @PostMapping("/maintenance-app/api/v1/pointSituationReport/addPointSituationReport") public R<?> addPointSituationReport(@RequestBody XpPointSituationReport xpPointSituationReport){ LoginOperationUser loginOperationUser = tokenService.getLoginOperationUser(); xpPointSituationReport.setOperationsUserId(loginOperationUser.getId()); xpPointSituationReport.setReportingTime(LocalDateTime.now()); xpPointSituationReport.setDeleted(false); xpPointSituationReportService.save(xpPointSituationReport); return R.ok(); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpPointSituationReportMapper.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.operation.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.model.operation.XpPointSituationReport; public interface XpPointSituationReportMapper extends BaseMapper<XpPointSituationReport> { } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpPointSituationReportService.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.operation.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.model.operation.XpPointSituationReport; public interface IXpPointSituationReportService extends IService<XpPointSituationReport> { } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java
@@ -17,6 +17,7 @@ import com.xiaopeng.api.vo.order.XpPointsListVo; import com.xiaopeng.api.vo.order.XpPointsSearchVo; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.utils.GeodesyUtil; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.evi.oss.service.AliOssService; @@ -274,10 +275,16 @@ } xpPoint.setPointPictures(JSONArray.toJSONString(jsonArray)); } if(null != query.getLongitude() && null != query.getLatitude()){ Map<String, Double> distance = GeodesyUtil.getDistance(query.getLongitude() + "," + query.getLatitude(), xpPoint.getPointLon() + "," + xpPoint.getPointLat()); xpPoint.setDistance(new BigDecimal(distance.get("WGS84"))); } } if(null != query.getLongitude() && null != query.getLatitude()){ //对距离进行排序 list.sort((o1, o2) -> o1.getDistance().compareTo(o2.getDistance()) * -1); } return list; } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPointSituationReportServiceImpl.java
New file @@ -0,0 +1,12 @@ package com.xiaopeng.operation.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.model.operation.XpPointSituationReport; import com.xiaopeng.operation.mapper.XpPointSituationReportMapper; import com.xiaopeng.operation.service.IXpPointSituationReportService; import org.springframework.stereotype.Service; @Service public class XpPointSituationReportServiceImpl extends ServiceImpl<XpPointSituationReportMapper, XpPointSituationReport> implements IXpPointSituationReportService { } xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpPointSituationReportMapper.xml
New file @@ -0,0 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.operation.mapper.XpPointSituationReportMapper"> </mapper> xp-robotaxi-payment-boot/xp-robotaxi-payment-boot.iml
New file @@ -0,0 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <module version="4"> <component name="AdditionalModuleElements"> <content url="file://$MODULE_DIR$" dumb="true"> <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> </content> </component> </module>