You've already forked FrameTour-BE
feat(printer):优化人脸样本使用逻辑并增强景区列表查询
- 修改 useSample 接口返回类型为 FaceRecognizeResp - 增加根据样本ID和类型查询来源实体的逻辑 - 在景区列表查询中添加参数校验和异常处理 - 完善景区信息处理流程,增加设备数量统计 -优化景区距离计算与筛选逻辑 - 增加人脸匹配后自动添加照片到用户相册的功能 - 添加 XML 映射文件中新的查询语句实现
This commit is contained in:
@@ -2,6 +2,7 @@ package com.ycwl.basic.controller.mobile;
|
|||||||
|
|
||||||
import com.ycwl.basic.annotation.IgnoreToken;
|
import com.ycwl.basic.annotation.IgnoreToken;
|
||||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||||
|
import com.ycwl.basic.model.mobile.face.FaceRecognizeResp;
|
||||||
import com.ycwl.basic.model.pc.printer.resp.MemberPrintResp;
|
import com.ycwl.basic.model.pc.printer.resp.MemberPrintResp;
|
||||||
import com.ycwl.basic.model.pc.printer.resp.PrinterResp;
|
import com.ycwl.basic.model.pc.printer.resp.PrinterResp;
|
||||||
import com.ycwl.basic.model.printer.req.FromSourceReq;
|
import com.ycwl.basic.model.printer.req.FromSourceReq;
|
||||||
@@ -37,7 +38,7 @@ public class AppPrinterController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/useSample/{sampleId}")
|
@PostMapping("/useSample/{sampleId}")
|
||||||
public ApiResponse<?> useSample(@PathVariable("sampleId") Long sampleId) throws IOException {
|
public ApiResponse<FaceRecognizeResp> useSample(@PathVariable("sampleId") Long sampleId) throws IOException {
|
||||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||||
return ApiResponse.success(printerService.useSample(worker.getUserId(), sampleId));
|
return ApiResponse.success(printerService.useSample(worker.getUserId(), sampleId));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,4 +105,6 @@ public interface SourceMapper {
|
|||||||
* @return 影响行数
|
* @return 影响行数
|
||||||
*/
|
*/
|
||||||
int addFromZTSource(SourceEntity source);
|
int addFromZTSource(SourceEntity source);
|
||||||
|
|
||||||
|
SourceEntity getBySampleIdAndType(Long faceSampleId, Integer type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,20 +220,52 @@ public class AppScenicServiceImpl implements AppScenicService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ScenicAppVO> scenicListByLnLa(ScenicIndexVO scenicIndexVO) {
|
public List<ScenicAppVO> scenicListByLnLa(ScenicIndexVO scenicIndexVO) {
|
||||||
|
// 参数校验
|
||||||
|
if (scenicIndexVO == null) {
|
||||||
|
log.warn("scenicListByLnLa 接收到空参数");
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
if (scenicIndexVO.getLatitude() == null || scenicIndexVO.getLongitude() == null) {
|
||||||
|
log.warn("scenicListByLnLa 缺少必要的经纬度参数, latitude={}, longitude={}",
|
||||||
|
scenicIndexVO.getLatitude(), scenicIndexVO.getLongitude());
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
// 从 scenicRepository 获取所有景区(1000个)
|
// 从 scenicRepository 获取所有景区(1000个)
|
||||||
ScenicReqQuery query = new ScenicReqQuery();
|
ScenicReqQuery query = new ScenicReqQuery();
|
||||||
query.setPageNum(1);
|
query.setPageNum(1);
|
||||||
query.setPageSize(1000);
|
query.setPageSize(1000);
|
||||||
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
|
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
|
||||||
|
|
||||||
|
if (scenicList == null || scenicList.isEmpty()) {
|
||||||
|
log.info("未查询到任何景区数据");
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
List<ScenicAppVO> list = new ArrayList<>();
|
List<ScenicAppVO> list = new ArrayList<>();
|
||||||
|
|
||||||
// 为每个景区获取详细信息(包含经纬度)
|
// 为每个景区获取详细信息(包含经纬度)
|
||||||
for (ScenicV2DTO scenicDTO : scenicList) {
|
for (ScenicV2DTO scenicDTO : scenicList) {
|
||||||
try {
|
try {
|
||||||
|
// ID 格式校验
|
||||||
|
if (StringUtils.isBlank(scenicDTO.getId())) {
|
||||||
|
log.warn("景区 ID 为空,跳过该景区");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 获取景区详细信息(包含经纬度)
|
// 获取景区详细信息(包含经纬度)
|
||||||
ScenicEntity scenicEntity = scenicRepository.getScenic(Long.parseLong(scenicDTO.getId()));
|
ScenicEntity scenicEntity = scenicRepository.getScenic(Long.parseLong(scenicDTO.getId()));
|
||||||
if (scenicEntity != null && scenicEntity.getLatitude() != null && scenicEntity.getLongitude() != null) {
|
if (scenicEntity == null) {
|
||||||
|
log.warn("景区详情查询失败, scenicId={}", scenicDTO.getId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scenicEntity.getLatitude() == null || scenicEntity.getLongitude() == null) {
|
||||||
|
log.warn("景区缺少经纬度信息, scenicId={}, scenicName={}",
|
||||||
|
scenicEntity.getId(), scenicEntity.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 计算距离
|
// 计算距离
|
||||||
BigDecimal distance = calculateDistance(
|
BigDecimal distance = calculateDistance(
|
||||||
scenicIndexVO.getLatitude(),
|
scenicIndexVO.getLatitude(),
|
||||||
@@ -261,17 +293,25 @@ public class AppScenicServiceImpl implements AppScenicService {
|
|||||||
scenicAppVO.setArea(scenicEntity.getArea());
|
scenicAppVO.setArea(scenicEntity.getArea());
|
||||||
scenicAppVO.setAddress(scenicEntity.getAddress());
|
scenicAppVO.setAddress(scenicEntity.getAddress());
|
||||||
scenicAppVO.setDistance(distance);
|
scenicAppVO.setDistance(distance);
|
||||||
scenicAppVO.setDeviceNum(deviceRepository.getAllDeviceByScenicId(scenicEntity.getId()).size());
|
|
||||||
|
// 获取设备数量
|
||||||
|
List<DeviceV2DTO> devices = deviceRepository.getAllDeviceByScenicId(scenicEntity.getId());
|
||||||
|
scenicAppVO.setDeviceNum(devices != null ? devices.size() : 0);
|
||||||
|
|
||||||
list.add(scenicAppVO);
|
list.add(scenicAppVO);
|
||||||
}
|
}
|
||||||
}
|
} catch (NumberFormatException e) {
|
||||||
|
log.error("景区 ID 格式错误,无法转换为 Long 类型, scenicId={}, error={}",
|
||||||
|
scenicDTO.getId(), e.getMessage());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 单个景区获取失败,继续处理下一个
|
log.error("处理景区信息时发生异常, scenicId={}, error={}",
|
||||||
continue;
|
scenicDTO != null ? scenicDTO.getId() : "unknown", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info("根据经纬度筛选景区完成, 输入坐标=({}, {}), 符合条件的景区数量={}",
|
||||||
|
scenicIndexVO.getLatitude(), scenicIndexVO.getLongitude(), list.size());
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ycwl.basic.service.printer;
|
package com.ycwl.basic.service.printer;
|
||||||
|
|
||||||
|
import com.ycwl.basic.model.mobile.face.FaceRecognizeResp;
|
||||||
import com.ycwl.basic.model.mobile.order.PriceObj;
|
import com.ycwl.basic.model.mobile.order.PriceObj;
|
||||||
import com.ycwl.basic.model.pc.printer.entity.PrinterEntity;
|
import com.ycwl.basic.model.pc.printer.entity.PrinterEntity;
|
||||||
import com.ycwl.basic.model.pc.printer.resp.MemberPrintResp;
|
import com.ycwl.basic.model.pc.printer.resp.MemberPrintResp;
|
||||||
@@ -56,7 +57,7 @@ public interface PrinterService {
|
|||||||
|
|
||||||
void setUserIsBuyItem(Long memberId, Long id, Long orderId);
|
void setUserIsBuyItem(Long memberId, Long id, Long orderId);
|
||||||
|
|
||||||
Object useSample(Long userId, Long sampleId);
|
FaceRecognizeResp useSample(Long userId, Long sampleId);
|
||||||
|
|
||||||
void autoAddPhotosToPreferPrint(Long faceId);
|
void autoAddPhotosToPreferPrint(Long faceId);
|
||||||
}
|
}
|
||||||
@@ -752,9 +752,10 @@ public class PrinterServiceImpl implements PrinterService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object useSample(Long userId, Long sampleId) {
|
public FaceRecognizeResp useSample(Long userId, Long sampleId) {
|
||||||
// 1. 查询 faceSample 获取其 URL
|
// 1. 查询 faceSample 获取其 URL
|
||||||
FaceSampleEntity faceSample = faceSampleMapper.getEntity(sampleId);
|
FaceSampleEntity faceSample = faceSampleMapper.getEntity(sampleId);
|
||||||
|
SourceEntity sourceEntity = sourceMapper.getBySampleIdAndType(sampleId, 2);
|
||||||
if (faceSample == null) {
|
if (faceSample == null) {
|
||||||
throw new BaseException("人脸样本不存在");
|
throw new BaseException("人脸样本不存在");
|
||||||
}
|
}
|
||||||
@@ -807,6 +808,12 @@ public class PrinterServiceImpl implements PrinterService {
|
|||||||
resp.setScenicId(scenicId);
|
resp.setScenicId(scenicId);
|
||||||
faceService.matchFaceId(faceId);
|
faceService.matchFaceId(faceId);
|
||||||
autoAddPhotosToPreferPrint(faceId);
|
autoAddPhotosToPreferPrint(faceId);
|
||||||
|
List<MemberPrintResp> userPhotoList = getUserPhotoList(userId, scenicId, faceId);
|
||||||
|
boolean noneMatch = userPhotoList.stream()
|
||||||
|
.noneMatch(item -> Strings.CI.equals(item.getOrigUrl(), sourceEntity.getUrl()));
|
||||||
|
if (noneMatch) {
|
||||||
|
addUserPhoto(userId, scenicId, sourceEntity.getUrl(), faceId);
|
||||||
|
}
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -354,4 +354,9 @@
|
|||||||
inner join member_source ms on s.id = ms.source_id
|
inner join member_source ms on s.id = ms.source_id
|
||||||
where ms.face_id = #{faceId} and s.type = 2
|
where ms.face_id = #{faceId} and s.type = 2
|
||||||
</select>
|
</select>
|
||||||
|
<select id="getBySampleIdAndType" resultType="com.ycwl.basic.model.pc.source.entity.SourceEntity">
|
||||||
|
select *
|
||||||
|
from source
|
||||||
|
where face_sample_id = #{faceSampleId} and type = #{type}
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user