Merge branch 'refs/heads/order_v2'

# Conflicts:
#	src/main/java/com/ycwl/basic/controller/mobile/manage/AppScenicAccountController.java
This commit is contained in:
2025-08-30 10:53:11 +08:00
112 changed files with 7427 additions and 948 deletions

View File

@@ -9,6 +9,7 @@ import com.ycwl.basic.model.mobile.scenic.account.ScenicLoginRespVO;
import com.ycwl.basic.model.mobile.scenic.account.ScenicRegisterReq;
import com.ycwl.basic.model.mobile.scenic.account.ScenicRegisterRespVO;
import com.ycwl.basic.model.pc.device.resp.DeviceRespVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.utils.ApiResponse;
@@ -20,7 +21,7 @@ import java.util.List;
* @Date:2024/12/6 10:23
*/
public interface AppScenicService {
ApiResponse<PageInfo<ScenicAppVO>> pageQuery(ScenicReqQuery scenicReqQuery);
ApiResponse<PageInfo<ScenicEntity>> pageQuery(ScenicReqQuery scenicReqQuery);
ApiResponse<ScenicDeviceCountVO> deviceCountByScenicId(Long scenicId);

View File

@@ -1,10 +1,11 @@
package com.ycwl.basic.service.mobile.impl;
import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.mapper.*;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.DeviceMapper;
import com.ycwl.basic.mapper.ExtraDeviceMapper;
import com.ycwl.basic.mapper.ScenicAccountMapper;
import com.ycwl.basic.model.jwt.JwtInfo;
import com.ycwl.basic.model.mobile.scenic.ScenicAppVO;
import com.ycwl.basic.model.mobile.scenic.ScenicDeviceCountVO;
@@ -16,9 +17,11 @@ import com.ycwl.basic.model.mobile.scenic.account.ScenicRegisterRespVO;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.model.pc.device.resp.DeviceRespVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicAccountEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppScenicService;
import com.ycwl.basic.service.pc.ScenicAccountService;
import com.ycwl.basic.utils.ApiResponse;
@@ -30,6 +33,7 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -43,8 +47,6 @@ import static com.ycwl.basic.constant.JwtRoleConstant.MERCHANT;
@Service
public class AppScenicServiceImpl implements AppScenicService {
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private DeviceMapper deviceMapper;
@Autowired
@@ -59,12 +61,19 @@ public class AppScenicServiceImpl implements AppScenicService {
private ExtraDeviceMapper extraDeviceMapper;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private ScenicRepository scenicRepository;
@Override
public ApiResponse<PageInfo<ScenicAppVO>> pageQuery(ScenicReqQuery scenicReqQuery) {
PageHelper.startPage(scenicReqQuery.getPageNum(), scenicReqQuery.getPageSize());
List<ScenicAppVO> list = scenicMapper.appList(scenicReqQuery);
PageInfo<ScenicAppVO> pageInfo = new PageInfo<>(list);
public ApiResponse<PageInfo<ScenicEntity>> pageQuery(ScenicReqQuery scenicReqQuery) {
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
List<ScenicEntity> list = scenicList.stream().map(scenic -> {
return scenicRepository.getScenic(Long.valueOf(scenic.getId()));
}).toList();
PageInfo<ScenicEntity> pageInfo = new PageInfo<>(list);
return ApiResponse.success(pageInfo);
}
@@ -77,7 +86,27 @@ public class AppScenicServiceImpl implements AppScenicService {
@Override
public ApiResponse<ScenicRespVO> getDetails(Long id) {
ScenicRespVO scenicRespVO = scenicMapper.getAppById(id);
ScenicEntity scenic = scenicRepository.getScenic(id);
ScenicRespVO scenicRespVO = new ScenicRespVO();
// 将ScenicEntity的值通过set/get方式写入到ScenicRespVO
if (scenic != null) {
scenicRespVO.setId(scenic.getId());
scenicRespVO.setName(scenic.getName());
scenicRespVO.setPhone(scenic.getPhone());
scenicRespVO.setLogoUrl(scenic.getLogoUrl());
scenicRespVO.setCoverUrl(scenic.getCoverUrl());
scenicRespVO.setIntroduction(scenic.getIntroduction());
scenicRespVO.setLongitude(scenic.getLongitude());
scenicRespVO.setLatitude(scenic.getLatitude());
scenicRespVO.setRadius(scenic.getRadius());
scenicRespVO.setProvince(scenic.getProvince());
scenicRespVO.setCity(scenic.getCity());
scenicRespVO.setArea(scenic.getArea());
scenicRespVO.setAddress(scenic.getAddress());
scenicRespVO.setKfCodeUrl(scenic.getKfCodeUrl());
}
ScenicDeviceCountVO scenicDeviceCountVO = deviceMapper.deviceCountByScenicId(id);
scenicRespVO.setLensNum(scenicDeviceCountVO.getTotalDeviceCount());
return ApiResponse.success(scenicRespVO);
@@ -171,8 +200,59 @@ public class AppScenicServiceImpl implements AppScenicService {
@Override
public List<ScenicAppVO> scenicListByLnLa(ScenicIndexVO scenicIndexVO) {
List<ScenicAppVO> scenicAppVOS = scenicMapper.scenicListByLnLa(scenicIndexVO);
return scenicAppVOS.stream().filter(scenic -> scenic.getDistance().compareTo(scenic.getRadius().multiply(BigDecimal.valueOf(1_000L))) < 0).toList();
// 从 scenicRepository 获取所有景区(1000个)
ScenicReqQuery query = new ScenicReqQuery();
query.setPageNum(1);
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
List<ScenicAppVO> list = new ArrayList<>();
// 为每个景区获取详细信息(包含经纬度)
for (ScenicV2DTO scenicDTO : scenicList) {
try {
// 获取景区详细信息(包含经纬度)
ScenicEntity scenicEntity = scenicRepository.getScenic(Long.parseLong(scenicDTO.getId()));
if (scenicEntity != null && scenicEntity.getLatitude() != null && scenicEntity.getLongitude() != null) {
// 计算距离
BigDecimal distance = calculateDistance(
scenicIndexVO.getLatitude(),
scenicIndexVO.getLongitude(),
scenicEntity.getLatitude(),
scenicEntity.getLongitude()
);
// 根据距离和范围筛选景区
if (scenicEntity.getRadius() != null &&
distance.compareTo(scenicEntity.getRadius().multiply(BigDecimal.valueOf(1_000L))) < 0) {
// 转换为 ScenicAppVO
ScenicAppVO scenicAppVO = new ScenicAppVO();
scenicAppVO.setId(scenicEntity.getId());
scenicAppVO.setName(scenicEntity.getName());
scenicAppVO.setPhone(scenicEntity.getPhone());
scenicAppVO.setIntroduction(scenicEntity.getIntroduction());
scenicAppVO.setCoverUrl(scenicEntity.getCoverUrl());
scenicAppVO.setLongitude(scenicEntity.getLongitude());
scenicAppVO.setLatitude(scenicEntity.getLatitude());
scenicAppVO.setRadius(scenicEntity.getRadius());
scenicAppVO.setProvince(scenicEntity.getProvince());
scenicAppVO.setCity(scenicEntity.getCity());
scenicAppVO.setArea(scenicEntity.getArea());
scenicAppVO.setAddress(scenicEntity.getAddress());
scenicAppVO.setDistance(distance);
scenicAppVO.setDeviceNum(deviceRepository.getAllDeviceByScenicId(scenicEntity.getId()).size());
list.add(scenicAppVO);
}
}
} catch (Exception e) {
// 单个景区获取失败,继续处理下一个
continue;
}
}
return list;
}
@Override
@@ -214,4 +294,29 @@ public class AppScenicServiceImpl implements AppScenicService {
deviceRespVOList.addAll(0, extraDeviceList);
return ApiResponse.success(deviceRespVOList);
}
/**
* 计算两点之间的距离(米)
* 使用 Haversine 公式
*/
private BigDecimal calculateDistance(BigDecimal lat1, BigDecimal lon1, BigDecimal lat2, BigDecimal lon2) {
if (lat1 == null || lon1 == null || lat2 == null || lon2 == null) {
return BigDecimal.ZERO;
}
final double R = 6371000; // 地球半径(米)
double lat1Rad = Math.toRadians(lat1.doubleValue());
double lat2Rad = Math.toRadians(lat2.doubleValue());
double deltaLat = Math.toRadians(lat2.subtract(lat1).doubleValue());
double deltaLon = Math.toRadians(lon2.subtract(lon1).doubleValue());
double a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
Math.cos(lat1Rad) * Math.cos(lat2Rad) *
Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double distance = R * c;
return BigDecimal.valueOf(distance);
}
}

View File

@@ -139,9 +139,9 @@ public class GoodsServiceImpl implements GoodsService {
List<SourceRespVO> goods = faceEntry.getValue();
return goods.stream().collect(Collectors.groupingBy(SourceRespVO::getType)).keySet().stream().filter(type -> {
if (Integer.valueOf(1).equals(type)) {
return !Integer.valueOf(1).equals(scenicConfig.getDisableSourceVideo());
return !Boolean.TRUE.equals(scenicConfig.getDisableSourceVideo());
} else if (Integer.valueOf(2).equals(type)) {
return !Integer.valueOf(1).equals(scenicConfig.getDisableSourceImage());
return !Boolean.TRUE.equals(scenicConfig.getDisableSourceImage());
}
return true;
}).map(type -> {