feat(puzzle): 新增拼图功能模块

- 新增AppPuzzleController控制器,提供拼图相关接口
- 实现根据faceId查询拼图数量和记录列表功能
- 实现根据recordId查询拼图详情和下载拼图资源功能
- 实现拼图价格计算和导入打印列表功能
- 在FaceServiceImpl中集成拼图记录展示逻辑
- 在OrderServiceImpl中新增PHOTO_LOG产品类型处理
- 在PrinterService中实现从拼图添加到打印列表的功能
- 完善拼图记录转换为内容页面VO的逻辑处理
This commit is contained in:
2025-11-20 23:11:04 +08:00
parent d458f918ed
commit 9123a1f6db
5 changed files with 390 additions and 1 deletions

View File

@@ -0,0 +1,232 @@
package com.ycwl.basic.controller.mobile;
import com.ycwl.basic.biz.OrderBiz;
import com.ycwl.basic.constant.SourceType;
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.pricing.dto.PriceCalculationRequest;
import com.ycwl.basic.pricing.dto.PriceCalculationResult;
import com.ycwl.basic.pricing.dto.ProductItem;
import com.ycwl.basic.pricing.enums.ProductType;
import com.ycwl.basic.pricing.service.IPriceCalculationService;
import com.ycwl.basic.puzzle.entity.PuzzleGenerationRecordEntity;
import com.ycwl.basic.puzzle.mapper.PuzzleGenerationRecordMapper;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.service.printer.PrinterService;
import com.ycwl.basic.utils.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/mobile/puzzle/v1")
@RequiredArgsConstructor
public class AppPuzzleController {
private final PuzzleGenerationRecordMapper recordMapper;
private final FaceRepository faceRepository;
private final IPriceCalculationService iPriceCalculationService;
private final PrinterService printerService;
private final OrderBiz orderBiz;
/**
* 根据faceId查询三拼图数量
*/
@GetMapping("/count/{faceId}")
public ApiResponse<Integer> countByFaceId(@PathVariable("faceId") Long faceId) {
if (faceId == null) {
return ApiResponse.fail("faceId不能为空");
}
int count = recordMapper.countByFaceId(faceId);
return ApiResponse.success(count);
}
/**
* 根据faceId查询所有三拼图记录
*/
@GetMapping("/list/{faceId}")
public ApiResponse<List<ContentPageVO>> listByFaceId(@PathVariable("faceId") Long faceId) {
if (faceId == null) {
return ApiResponse.fail("faceId不能为空");
}
List<PuzzleGenerationRecordEntity> records = recordMapper.listByFaceId(faceId);
List<ContentPageVO> result = records.stream()
.map(this::convertToContentPageVO)
.collect(Collectors.toList());
return ApiResponse.success(result);
}
/**
* 根据recordId查询单个三拼图记录
*/
@GetMapping("/detail/{recordId}")
public ApiResponse<ContentPageVO> getByRecordId(@PathVariable("recordId") Long recordId) {
if (recordId == null) {
return ApiResponse.fail("recordId不能为空");
}
PuzzleGenerationRecordEntity record = recordMapper.getById(recordId);
if (record == null) {
return ApiResponse.fail("未找到对应的拼图记录");
}
ContentPageVO result = convertToContentPageVO(record);
return ApiResponse.success(result);
}
/**
* 根据recordId下载拼图资源
*/
@GetMapping("/download/{recordId}")
public ApiResponse<List<String>> download(@PathVariable("recordId") Long recordId) {
if (recordId == null) {
return ApiResponse.fail("recordId不能为空");
}
PuzzleGenerationRecordEntity record = recordMapper.getById(recordId);
if (record == null) {
return ApiResponse.fail("未找到对应的拼图记录");
}
String resultImageUrl = record.getResultImageUrl();
if (resultImageUrl == null || resultImageUrl.isEmpty()) {
return ApiResponse.fail("该拼图记录没有可用的图片URL");
}
return ApiResponse.success(Collections.singletonList(resultImageUrl));
}
/**
* 根据recordId查询拼图价格
*/
@GetMapping("/price/{recordId}")
public ApiResponse<PriceCalculationResult> getPriceByRecordId(@PathVariable("recordId") Long recordId) {
if (recordId == null) {
return ApiResponse.fail("recordId不能为空");
}
PuzzleGenerationRecordEntity record = recordMapper.getById(recordId);
if (record == null) {
return ApiResponse.fail("未找到对应的拼图记录");
}
FaceEntity face = faceRepository.getFace(record.getFaceId());
if (face == null) {
return ApiResponse.fail("未找到对应的人脸信息");
}
PriceCalculationRequest calculationRequest = new PriceCalculationRequest();
ProductItem productItem = new ProductItem();
productItem.setProductType(ProductType.PHOTO_LOG);
productItem.setProductId(record.getTemplateId().toString());
productItem.setPurchaseCount(1);
productItem.setScenicId(face.getScenicId().toString());
calculationRequest.setProducts(Collections.singletonList(productItem));
calculationRequest.setUserId(face.getMemberId());
calculationRequest.setFaceId(record.getFaceId());
calculationRequest.setPreviewOnly(true); // 仅查询价格,不实际使用优惠
PriceCalculationResult calculationResult = iPriceCalculationService.calculatePrice(calculationRequest);
return ApiResponse.success(calculationResult);
}
/**
* 将拼图导入到打印列表
*/
@PostMapping("/import-to-print/{recordId}")
public ApiResponse<Integer> importToPrint(@PathVariable("recordId") Long recordId) {
if (recordId == null) {
return ApiResponse.fail("recordId不能为空");
}
// 查询拼图记录
PuzzleGenerationRecordEntity record = recordMapper.getById(recordId);
if (record == null) {
return ApiResponse.fail("未找到对应的拼图记录");
}
// 检查是否有图片URL
String resultImageUrl = record.getResultImageUrl();
if (resultImageUrl == null || resultImageUrl.isEmpty()) {
return ApiResponse.fail("该拼图记录没有可用的图片URL");
}
// 获取人脸信息
FaceEntity face = faceRepository.getFace(record.getFaceId());
if (face == null) {
return ApiResponse.fail("未找到对应的人脸信息");
}
// 调用服务添加到打印列表
Integer memberPrintId = printerService.addUserPhotoFromPuzzle(
face.getMemberId(),
face.getScenicId(),
record.getFaceId(),
resultImageUrl,
recordId
);
if (memberPrintId == null) {
return ApiResponse.fail("添加到打印列表失败");
}
return ApiResponse.success(memberPrintId);
}
/**
* 将PuzzleGenerationRecordEntity转换为ContentPageVO
*/
private ContentPageVO convertToContentPageVO(PuzzleGenerationRecordEntity record) {
ContentPageVO vo = new ContentPageVO();
// 内容类型为3(拼图)
vo.setContentType(3);
// 源素材类型为3(拼图)
vo.setSourceType(3);
vo.setGroup("拼图");
// 只要存在记录,lockType不为0(设置为-1表示已生成)
vo.setLockType(-1);
// 通过faceId填充scenicId的信息
FaceEntity face = faceRepository.getFace(record.getFaceId());
if (record.getFaceId() != null) {
vo.setScenicId(face.getScenicId());
}
// contentId为生成记录id
vo.setContentId(record.getId());
// templateCoverUrl和生成的图是一致的
vo.setTemplateCoverUrl(record.getResultImageUrl());
// 设置模板ID
vo.setTemplateId(record.getTemplateId());
IsBuyRespVO isBuyRespVO = orderBiz.isBuy(face.getMemberId(), face.getScenicId(), 3, face.getId());
if (isBuyRespVO.isBuy()) {
vo.setIsBuy(1);
} else {
vo.setIsBuy(0);
PriceCalculationRequest calculationRequest = new PriceCalculationRequest();
ProductItem productItem = new ProductItem();
productItem.setProductType(ProductType.PHOTO_LOG);
productItem.setProductId(record.getTemplateId().toString());
productItem.setPurchaseCount(1);
productItem.setScenicId(face.getScenicId().toString());
calculationRequest.setProducts(Collections.singletonList(productItem));
calculationRequest.setUserId(face.getMemberId());
calculationRequest.setFaceId(record.getFaceId());
calculationRequest.setPreviewOnly(true); // 仅查询价格,不实际使用优惠
PriceCalculationResult calculationResult = iPriceCalculationService.calculatePrice(calculationRequest);
if (calculationResult.getFinalAmount().compareTo(BigDecimal.ZERO) > 0) {
vo.setFreeCount(0);
} else {
vo.setFreeCount(1);
}
}
return vo;
}
}