refactor(scenic): 重构景区相关接口和缓存机制

- 移除 ScenicMapper 接口,将相关方法移至 ScenicRepository
- 修改景区列表查询逻辑,使用 ScenicRepository 的 list 方法
- 优化景区详情获取方式,使用 ScenicRepository 的 getScenicBasic 方法
- 重构缓存机制,增加对景区基本信息的缓存
- 优化 AppScenicService 和 ScenicService接口,使用 ScenicV2DTO 替代 ScenicRespV
This commit is contained in:
2025-08-27 16:37:57 +08:00
parent 21f76ff9c5
commit f2ac6aaea0
20 changed files with 324 additions and 474 deletions

View File

@@ -3,12 +3,12 @@ package com.ycwl.basic.controller.mobile;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.annotation.IgnoreToken;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.model.jwt.JwtInfo;
import com.ycwl.basic.model.mobile.scenic.ScenicAppVO;
import com.ycwl.basic.model.mobile.scenic.ScenicDeviceCountVO;
import com.ycwl.basic.model.mobile.scenic.ScenicIndexVO;
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
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.ScenicConfigResp;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
@@ -16,11 +16,14 @@ import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppScenicService;
import com.ycwl.basic.service.pc.FaceService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@@ -49,7 +52,7 @@ public class AppScenicController {
// 分页查询景区列表
@PostMapping("/page")
public ApiResponse<PageInfo<ScenicAppVO>> pageQuery(@RequestBody ScenicReqQuery scenicReqQuery){
public ApiResponse<PageInfo<ScenicEntity>> pageQuery(@RequestBody ScenicReqQuery scenicReqQuery){
String userId = BaseContextHandler.getUserId();
if (ENABLED_USER_IDs.contains(userId)) {
return appScenicService.pageQuery(scenicReqQuery);

View File

@@ -2,14 +2,15 @@ package com.ycwl.basic.controller.mobile.manage;
import com.ycwl.basic.annotation.IgnoreToken;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.model.mobile.scenic.account.ScenicLoginOldRespVO;
import com.ycwl.basic.model.mobile.scenic.account.ScenicLoginReq;
import com.ycwl.basic.model.mobile.scenic.account.ScenicLoginRespVO;
import com.ycwl.basic.model.mobile.weChat.DTO.WeChatUserInfoDTO;
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.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppScenicService;
import com.ycwl.basic.service.pc.ScenicAccountService;
import com.ycwl.basic.service.pc.ScenicService;
@@ -23,7 +24,6 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -44,6 +44,8 @@ public class AppScenicAccountController {
private AppScenicService scenicService;
@Autowired
private ScenicService adminScenicService;
@Autowired
private ScenicRepository scenicRepository;
// 登录
@PostMapping("/login")
@@ -65,8 +67,8 @@ public class AppScenicAccountController {
}
@GetMapping("/myScenicList")
public ApiResponse<List<ScenicRespVO>> myScenicList() {
List<ScenicRespVO> list = Collections.emptyList();
public ApiResponse<List<ScenicV2DTO>> myScenicList() {
List<ScenicV2DTO> list = Collections.emptyList();
if (Strings.CS.equals(BaseContextHandler.getRoleId(), MERCHANT.type)) {
String userId = BaseContextHandler.getUserId();
ScenicAccountEntity account = accountService.getScenicAccountById(Long.valueOf(userId));
@@ -74,10 +76,12 @@ public class AppScenicAccountController {
return ApiResponse.fail("景区账号未绑定景区");
}
list = account.getScenicId().stream()
.map(id -> scenicService.getDetails(id).getData())
.map(id -> scenicRepository.getScenicBasic(id))
.toList();
} else if (Strings.CS.equals(BaseContextHandler.getRoleId(), ADMIN.type)) {
list = adminScenicService.list(new ScenicReqQuery()).getData();
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
list = scenicRepository.list(query);
}
return ApiResponse.success(list);
}

View File

@@ -1,13 +1,12 @@
package com.ycwl.basic.controller.pc;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.model.mobile.statistic.req.CommonQueryReq;
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicAccountEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppScenicService;
import com.ycwl.basic.service.mobile.AppStatisticsService;
import com.ycwl.basic.service.pc.ScenicAccountService;
@@ -17,16 +16,20 @@ import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.enums.StorageAcl;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.WxMpUtil;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
import org.apache.commons.lang3.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.util.Collections;
import java.util.List;
import static com.ycwl.basic.constant.JwtRoleConstant.ADMIN;
import static com.ycwl.basic.constant.JwtRoleConstant.MERCHANT;
/**
@@ -105,19 +108,19 @@ public class ScenicController {
}
@GetMapping("/myScenicList")
public ApiResponse<List<ScenicRespVO>> myScenicList() {
List<ScenicRespVO> list = Collections.emptyList();
public ApiResponse<List<ScenicV2DTO>> myScenicList() {
List<ScenicV2DTO> list = Collections.emptyList();
if (Strings.CS.equals(BaseContextHandler.getRoleId(), MERCHANT.type)) {
String userId = BaseContextHandler.getUserId();
ScenicAccountEntity account = accountService.getScenicAccountById(Long.valueOf(userId));
if (account == null || account.getScenicId().isEmpty()) {
return ApiResponse.fail("景区账号未绑定景区");
}
list = account.getScenicId().stream().map(id -> {
return appScenicService.getDetails(id).getData();
}).toList();
} else {
list = scenicService.list(new ScenicReqQuery()).getData();
list = account.getScenicId().stream().map(id -> scenicRepository.getScenicBasic(id)).toList();
} else if (Strings.CS.equals(BaseContextHandler.getRoleId(), ADMIN.type)) {
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
list = scenicRepository.list(query);
}
return ApiResponse.success(list);
}

View File

@@ -9,18 +9,26 @@ import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterPageResponse;
import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterRequest;
import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigListResponse;
import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest;
import com.ycwl.basic.integration.scenic.service.ScenicConfigIntegrationService;
import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService;
import com.ycwl.basic.utils.ApiResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
@@ -165,6 +173,24 @@ public class ScenicV2Controller {
}
}
/**
* 景区列表查询(默认1000条)
* 只支持根据状态筛选
*/
@GetMapping("/list")
public ApiResponse<ScenicV2ListResponse> listScenicsByStatus(@RequestParam(required = false) Integer status) {
log.info("查询景区列表, status: {}", status);
try {
// 默认查询1000条数据,第1页
ScenicV2ListResponse scenics = scenicIntegrationService.listScenics(1, 1000, status, null);
return ApiResponse.success(scenics);
} catch (Exception e) {
log.error("查询景区列表失败, status: {}", status, e);
return ApiResponse.fail("查询景区列表失败: " + e.getMessage());
}
}
// ========== 景区配置管理 ==========
/**

View File

@@ -1,33 +0,0 @@
package com.ycwl.basic.mapper;
import com.ycwl.basic.model.mobile.scenic.ScenicAppVO;
import com.ycwl.basic.model.mobile.scenic.ScenicIndexVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.utils.ApiResponse;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @Author:longbinbin
* @Date:2024/12/2 10:07
* 景区管理表
*/
@Mapper
public interface ScenicMapper {
List<ScenicRespVO> list(ScenicReqQuery scenicReqQuery);
List<ScenicAppVO> appList(ScenicReqQuery scenicReqQuery);
/**
* 通过经纬度计算景区距离
*
* @param scenicIndexVO
* @return
*/
List<ScenicAppVO> scenicListByLnLa(ScenicIndexVO scenicIndexVO);
}

View File

@@ -1,11 +1,8 @@
package com.ycwl.basic.model.pc.scenic.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Author:longbinbin
@@ -60,8 +57,6 @@ public class ScenicEntity {
* 状态 1启用0关闭
*/
private String status;
private Date createTime;
private Date updateTime;
/**
* 景区源素材价格,元
*/

View File

@@ -1,6 +1,11 @@
package com.ycwl.basic.repository;
import com.ycwl.basic.utils.JacksonUtil;
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
import com.ycwl.basic.integration.common.util.ConfigValueUtil;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService;
import com.ycwl.basic.mapper.MpConfigMapper;
import com.ycwl.basic.mapper.MpNotifyConfigMapper;
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
@@ -8,13 +13,10 @@ import com.ycwl.basic.model.pc.mp.MpNotifyConfigEntity;
import com.ycwl.basic.model.pc.mp.ScenicMpNotifyVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
import com.ycwl.basic.integration.common.util.ConfigValueUtil;
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.pay.enums.PayAdapterType;
import com.ycwl.basic.storage.enums.StorageType;
import com.ycwl.basic.utils.JacksonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@@ -31,6 +33,7 @@ public class ScenicRepository {
private ScenicIntegrationService scenicIntegrationService;
public static final String SCENIC_CACHE_KEY = "scenic:%s";
public static final String SCENIC_BASIC_CACHE_KEY = "scenic:basic:%s";
public static final String SCENIC_FULL_CACHE_KEY = "scenic:f%s";
public static final String SCENIC_CONFIG_CACHE_KEY = "scenic:%s:config";
public static final String SCENIC_MP_CACHE_KEY = "scenic:%s:mp";
@@ -38,6 +41,30 @@ public class ScenicRepository {
@Autowired
private MpNotifyConfigMapper mpNotifyConfigMapper;
public ScenicV2DTO getScenicBasic(Long id) {
String key = String.format(SCENIC_BASIC_CACHE_KEY, id);
try {
ScenicV2DTO scenicDTO = scenicIntegrationService.getScenic(id);
// 请求成功,写入缓存
if (scenicDTO != null) {
redisTemplate.opsForValue().set(
key,
JacksonUtil.toJSONString(scenicDTO)
);
}
return scenicDTO;
} catch (Exception e) {
// 请求失败,尝试从缓存获取历史成功数据
String cacheKey = key;
if (redisTemplate.hasKey(cacheKey)) {
return JacksonUtil.parseObject(redisTemplate.opsForValue().get(cacheKey), ScenicV2DTO.class);
}
// 缓存也没有,返回null
return null;
}
}
public ScenicEntity getScenic(Long id) {
String key = String.format(SCENIC_CACHE_KEY, id);
try {
@@ -155,8 +182,34 @@ public class ScenicRepository {
return null;
}
public List<ScenicV2DTO> list(ScenicReqQuery scenicReqQuery) {
try {
// 将 ScenicReqQuery 参数转换为 zt-scenic 服务需要的参数
Integer page = scenicReqQuery.getPageNum();
Integer pageSize = scenicReqQuery.getPageSize();
Integer status = null;
if (scenicReqQuery.getStatus() != null) {
status = Integer.valueOf(scenicReqQuery.getStatus());
}
String name = scenicReqQuery.getName();
// 调用 zt-scenic 服务的 list 方法
ScenicV2ListResponse response = scenicIntegrationService.listScenics(page, pageSize, status, name);
// 将 ScenicV2DTO 列表转换为 ScenicEntity 列表
if (response != null && response.getList() != null) {
return response.getList();
}
return new java.util.ArrayList<>();
} catch (Exception e) {
// 如果调用失败,返回空列表
return new java.util.ArrayList<>();
}
}
public void clearCache(Long scenicId) {
redisTemplate.delete(String.format(SCENIC_CACHE_KEY, scenicId));
redisTemplate.delete(String.format(SCENIC_BASIC_CACHE_KEY, scenicId));
redisTemplate.delete(String.format(SCENIC_FULL_CACHE_KEY, scenicId));
redisTemplate.delete(String.format(SCENIC_CONFIG_CACHE_KEY, scenicId));
redisTemplate.delete(String.format(SCENIC_MP_CACHE_KEY, scenicId));
@@ -172,8 +225,6 @@ public class ScenicRepository {
entity.setName(dto.getName());
entity.setMpId(dto.getMpId());
entity.setStatus(dto.getStatus().toString());
entity.setCreateTime(new java.util.Date(dto.getCreateTime()));
entity.setUpdateTime(new java.util.Date(dto.getUpdateTime()));
return entity;
}
@@ -186,8 +237,6 @@ public class ScenicRepository {
entity.setName(dto.getName());
entity.setMpId(dto.getMpId());
entity.setStatus(dto.getStatus().toString());
entity.setCreateTime(new java.util.Date(dto.getCreateTime()));
entity.setUpdateTime(new java.util.Date(dto.getUpdateTime()));
if (dto.getConfig() != null) {
entity.setAddress(ConfigValueUtil.getStringValue(dto.getConfig(), "address"));
entity.setArea(ConfigValueUtil.getStringValue(dto.getConfig(), "area"));

View File

@@ -13,7 +13,6 @@ import com.ycwl.basic.facebody.entity.AddFaceResp;
import com.ycwl.basic.mapper.DeviceMapper;
import com.ycwl.basic.mapper.CustomUploadTaskMapper;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.model.custom.entity.CustomUploadTaskEntity;

View File

@@ -7,6 +7,7 @@ import com.ycwl.basic.model.mobile.scenic.ScenicIndexVO;
import com.ycwl.basic.model.mobile.scenic.account.ScenicLoginReq;
import com.ycwl.basic.model.mobile.scenic.account.ScenicLoginRespVO;
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;
@@ -18,7 +19,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;
@@ -14,7 +15,6 @@ import com.ycwl.basic.model.mobile.scenic.account.ScenicLoginRespVO;
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.ScenicConfigEntity;
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;
@@ -31,6 +31,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;
@@ -44,8 +45,6 @@ import static com.ycwl.basic.constant.JwtRoleConstant.MERCHANT;
@Service
public class AppScenicServiceImpl implements AppScenicService {
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private DeviceMapper deviceMapper;
@Autowired
@@ -64,10 +63,15 @@ public class AppScenicServiceImpl implements AppScenicService {
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);
}
@@ -140,8 +144,58 @@ 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);
list.add(scenicAppVO);
}
}
} catch (Exception e) {
// 单个景区获取失败,继续处理下一个
continue;
}
}
return list;
}
@Override
@@ -183,4 +237,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

@@ -1,11 +1,8 @@
package com.ycwl.basic.service.pc;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.pay.adapter.IPayAdapter;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.utils.ApiResponse;
@@ -17,7 +14,7 @@ import java.util.List;
* @Date:2024/12/3 15:22
*/
public interface ScenicService {
ApiResponse<List<ScenicRespVO>> list(ScenicReqQuery scenicReqQuery);
ApiResponse<List<ScenicV2DTO>> list(ScenicReqQuery scenicReqQuery);
IStorageAdapter getScenicStorageAdapter(Long scenicId);

View File

@@ -1,39 +1,27 @@
package com.ycwl.basic.service.pc.impl;
import com.ycwl.basic.utils.JacksonUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.facebody.FaceBodyFactory;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.mapper.ScenicAccountMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.model.pc.scenic.entity.ScenicAccountEntity;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.pay.PayFactory;
import com.ycwl.basic.pay.adapter.IPayAdapter;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.exceptions.StorageUnsupportedException;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.SnowFlakeUtil;
import com.ycwl.basic.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
/**
* @Author:longbinbin
* @Date:2024/12/3 15:25
@@ -41,15 +29,13 @@ import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
@Slf4j
@Service
public class ScenicServiceImpl implements ScenicService {
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private ScenicRepository scenicRepository;
@Override
@Deprecated
public ApiResponse<List<ScenicRespVO>> list(ScenicReqQuery scenicReqQuery) {
return ApiResponse.success(scenicMapper.list(scenicReqQuery));
public ApiResponse<List<ScenicV2DTO>> list(ScenicReqQuery scenicReqQuery) {
return ApiResponse.success(scenicRepository.list(scenicReqQuery));
}
private static final Map<Long, IStorageAdapter> scenicStorageAdapterMap = new ConcurrentHashMap<>();

View File

@@ -1,9 +1,9 @@
package com.ycwl.basic.task;
import cn.hutool.core.date.DateUtil;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.CouponMapper;
import com.ycwl.basic.mapper.MemberMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.model.pc.coupon.req.CouponQueryReq;
import com.ycwl.basic.model.pc.coupon.resp.CouponRespVO;
@@ -12,8 +12,6 @@ import com.ycwl.basic.model.pc.mp.MpConfigEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
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.model.pc.template.resp.TemplateRespVO;
import com.ycwl.basic.notify.NotifyFactory;
import com.ycwl.basic.notify.adapters.INotifyAdapter;
import com.ycwl.basic.notify.entity.NotifyContent;
@@ -47,10 +45,6 @@ public class DownloadNotificationTasker {
@Autowired
private MemberMapper memberMapper;
@Autowired
private TemplateRepository templateRepository;
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private CouponMapper couponMapper;
@Scheduled(cron = "0 0 21 * * *")
@@ -168,7 +162,9 @@ public class DownloadNotificationTasker {
@Scheduled(cron = "0 0 * * * *")
public void sendExtraDownloadNotification() {
log.info("开始执行定时任务");
List<ScenicRespVO> scenicList = scenicMapper.list(new ScenicReqQuery());
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
if (scenicList.isEmpty()) {
return;
}
@@ -177,7 +173,7 @@ public class DownloadNotificationTasker {
int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
calendar.clear();
scenicList.parallelStream().forEach(scenic -> {
Long scenicId = scenic.getId();
Long scenicId = Long.parseLong(scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig == null) {
return;

View File

@@ -7,7 +7,6 @@ import com.ycwl.basic.facebody.adapter.AliFaceBodyAdapter;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.mapper.TemplateMapper;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
@@ -40,8 +39,6 @@ import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
@EnableScheduling
@Slf4j
public class DynamicTaskGenerator {
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private TemplateMapper templateMapper;
@Autowired

View File

@@ -4,9 +4,9 @@ import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.ycwl.basic.constant.StorageConstant;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
@@ -16,7 +16,6 @@ import com.ycwl.basic.model.pc.faceSample.req.FaceSampleReqQuery;
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.model.pc.source.req.SourceReqQuery;
import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
import com.ycwl.basic.model.pc.video.req.VideoReqQuery;
@@ -46,8 +45,6 @@ import static com.ycwl.basic.constant.StorageConstant.VIID_FACE;
@Slf4j
@Profile("prod")
public class FaceCleaner {
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private FaceSampleMapper faceSampleMapper;
@Autowired
@@ -64,25 +61,27 @@ public class FaceCleaner {
@Scheduled(cron = "0 0 1 * * ?")
public void deleteExpireSample(){
ScenicReqQuery scenicQuery = new ScenicReqQuery();
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.parallelStream().forEach(scenic -> {
log.info("当前景区{},开始删除人脸样本", scenic.getId());
IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId());
Long scenicId = Long.parseLong(scenic.getId());
log.info("当前景区{},开始删除人脸样本", scenicId);
IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(scenicId);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
Integer sampleStoreDay = scenicConfig.getSampleStoreDay();
if (sampleStoreDay == null) {
log.info("当前景区{},人脸样本保存天数未设置,默认7天", scenic.getId());
sampleStoreDay = 7;
}
Date sampleEndDate = DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -sampleStoreDay);
List<FaceSampleEntity> faceSampleList = faceSampleMapper.listEntityBeforeDate(scenic.getId(), sampleEndDate);
List<FaceSampleEntity> faceSampleList = faceSampleMapper.listEntityBeforeDate(scenicId, sampleEndDate);
if (faceSampleList.isEmpty()) {
log.info("当前景区{},人脸样本为空", scenic.getId());
return;
}
faceSampleList.forEach(faceSample -> {
boolean success = adapter.deleteFace(String.valueOf(scenic.getId()), faceSample.getId().toString());
boolean success = adapter.deleteFace(scenic.getId(), faceSample.getId().toString());
if (success) {
log.info("当前景区{},人脸样本ID{},删除成功", scenic.getId(), faceSample.getId());
faceSampleMapper.deleteById(faceSample.getId());
@@ -95,21 +94,23 @@ public class FaceCleaner {
@Scheduled(cron = "0 45 2 * * ?")
public void deleteExpireFace() {
ScenicReqQuery scenicQuery = new ScenicReqQuery();
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.parallelStream().forEach(scenic -> {
Long scenicId = Long.parseLong(scenic.getId());
log.info("当前景区{},开始删除用户人脸", scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId());
IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(scenicId);
Integer faceStoreDay = scenicConfig.getFaceStoreDay();
if (faceStoreDay == null) {
log.info("当前景区{},人脸样本保存天数未设置,默认3天", scenic.getName());
faceStoreDay = 3;
}
FaceReqQuery req = new FaceReqQuery();
req.setScenicId(scenic.getId());
req.setScenicId(scenicId);
Date faceEndDate = DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -faceStoreDay);
List<FaceEntity> list = faceMapper.listUnpaidEntityBeforeDate(scenic.getId(), faceEndDate);
List<FaceEntity> list = faceMapper.listUnpaidEntityBeforeDate(scenicId, faceEndDate);
list.forEach(face -> {
boolean result = adapter.deleteFace(USER_FACE_DB_NAME+face.getScenicId(), face.getId().toString());
if (result) {
@@ -130,10 +131,12 @@ public class FaceCleaner {
@Scheduled(cron = "0 0 1 * * ?")
public void deleteNotBuySource(){
ScenicReqQuery scenicQuery = new ScenicReqQuery();
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.parallelStream().forEach(scenic -> {
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId());
Long scenicId = Long.valueOf(scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig == null) {
log.info("当前景区{},无配置信息", scenic.getName());
return;
@@ -144,17 +147,19 @@ public class FaceCleaner {
}
int expireDay = scenicConfig.getUserSourceExpireDay();
Date endDate = DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -expireDay);
int deleteCount = sourceMapper.deleteNotBuyRelations(scenic.getId(), endDate);
int deleteCount = sourceMapper.deleteNotBuyRelations(scenicId, endDate);
log.info("当前景区{},删除关联素材{}个", scenic.getName(), deleteCount);
});
}
@Scheduled(cron = "0 15 1 * * ?")
public void deleteNotBuyVideos(){
ScenicReqQuery scenicQuery = new ScenicReqQuery();
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.parallelStream().forEach(scenic -> {
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId());
Long scenicId = Long.valueOf(scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig == null) {
log.info("当前景区{},无配置信息", scenic.getName());
return;
@@ -165,7 +170,7 @@ public class FaceCleaner {
}
int expireDay = scenicConfig.getVideoStoreDay();
Date endDate = DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -expireDay);
int deleteCount = videoMapper.deleteNotBuyRelations(scenic.getId(), endDate);
int deleteCount = videoMapper.deleteNotBuyRelations(scenicId, endDate);
int deleteVideoCount = videoMapper.deleteUselessVideo();
log.info("当前景区{},删除VLOG关系{}个,删除VLOG记录{}个", scenic.getName(), deleteCount, deleteVideoCount);
});
@@ -173,10 +178,12 @@ public class FaceCleaner {
@Scheduled(cron = "0 30 1 * * ?")
public void deleteExpiredSource(){
ScenicReqQuery scenicQuery = new ScenicReqQuery();
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.parallelStream().forEach(scenic -> {
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId());
Long scenicId = Long.valueOf(scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig == null) {
log.info("当前景区{},无配置信息", scenic.getName());
return;
@@ -193,10 +200,10 @@ public class FaceCleaner {
} else {
log.info("当前景区{},原始素材保存天数未设置,默认7天", scenic.getName());
}
if (Integer.valueOf(1).equals(scenicConfig.getDisableSourceVideo())) {
if (Boolean.TRUE.equals(scenicConfig.getDisableSourceVideo())) {
return;
}
if (Integer.valueOf(1).equals(scenicConfig.getDisableSourceImage())) {
if (Boolean.TRUE.equals(scenicConfig.getDisableSourceImage())) {
return;
}
log.info("当前景区{},开始删除原始素材", scenic.getName());
@@ -240,12 +247,16 @@ public class FaceCleaner {
log.info("开始清理源视频素材文件");
List<SourceRespVO> list = sourceMapper.list(new SourceReqQuery());
ArrayList<String> adapterIdentity = new ArrayList<>();
scenicMapper.list(new ScenicReqQuery()).forEach(scenic -> {
if (disableDeleteScenicIds.contains(scenic.getId().toString())) {
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.forEach(scenic -> {
Long scenicId = Long.valueOf(scenic.getId());
if (disableDeleteScenicIds.contains(scenic.getId())) {
log.info("景区【{}】禁止删除文件,跳过!", scenic.getName());
return;
}
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenic.getId());
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
String identity = adapter.identity();
if (!adapterIdentity.contains(identity)) {
log.info("因为Identity相同,跳过");
@@ -291,12 +302,16 @@ public class FaceCleaner {
log.info("开始清理视频文件");
List<VideoRespVO> list = videoMapper.list(new VideoReqQuery());
ArrayList<String> adapterIdentity = new ArrayList<>();
scenicMapper.list(new ScenicReqQuery()).forEach(scenic -> {
if (disableDeleteScenicIds.contains(scenic.getId().toString())) {
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.forEach(scenic -> {
Long scenicId = Long.valueOf(scenic.getId());
if (disableDeleteScenicIds.contains(scenic.getId())) {
log.info("景区【{}】禁止删除文件,跳过!", scenic.getName());
return;
}
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenic.getId());
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
String identity = adapter.identity();
if (!adapterIdentity.contains(identity)) {
adapterIdentity.add(identity);

View File

@@ -1,14 +1,14 @@
package com.ycwl.basic.task;
import cn.hutool.core.date.DateUtil;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.ScenicDeviceStatsMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.mapper.StatisticsMapper;
import com.ycwl.basic.model.mobile.statistic.req.CommonQueryReq;
import com.ycwl.basic.model.mobile.statistic.resp.AppStatisticsFunnelVO;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.model.pc.scenicDeviceStats.entity.ScenicDeviceStatsEntity;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppStatisticsService;
import com.ycwl.basic.utils.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
@@ -31,7 +31,8 @@ public class ScenicStatsTask {
@Autowired
private AppStatisticsService statisticsService;
@Autowired
private ScenicMapper scenicMapper;
private ScenicRepository scenicRepository;
@Scheduled(cron = "0 1 0 * * *")
public void countDeviceStats() {
Date yesterdayStart = DateUtil.beginOfDay(DateUtil.yesterday());
@@ -58,16 +59,19 @@ public class ScenicStatsTask {
public void countScenicStats() {
Date yesterdayStart = DateUtil.beginOfDay(DateUtil.yesterday());
Date yesterdayEnd = DateUtil.endOfDay(yesterdayStart);
List<ScenicRespVO> list = scenicMapper.list(new ScenicReqQuery());
list.forEach((scenic) -> {
CommonQueryReq query = new CommonQueryReq();
query.setScenicId(scenic.getId());
query.setStartTime(yesterdayStart);
query.setEndTime(yesterdayEnd);
query.setRealtime(true);
ApiResponse<AppStatisticsFunnelVO> resp = statisticsService.userConversionFunnel(query);
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.forEach((scenic) -> {
CommonQueryReq commonQueryReq = new CommonQueryReq();
Long scenicId = Long.valueOf(scenic.getId());
commonQueryReq.setScenicId(scenicId);
commonQueryReq.setStartTime(yesterdayStart);
commonQueryReq.setEndTime(yesterdayEnd);
commonQueryReq.setRealtime(true);
ApiResponse<AppStatisticsFunnelVO> resp = statisticsService.userConversionFunnel(commonQueryReq);
AppStatisticsFunnelVO data = resp.getData();
statisticsMapper.insertStat(scenic.getId(), yesterdayStart, data);
statisticsMapper.insertStat(scenicId, yesterdayStart, data);
});
}
}

View File

@@ -2,21 +2,16 @@ package com.ycwl.basic.task;
import cn.hutool.core.date.DateUtil;
import com.ycwl.basic.biz.TemplateBiz;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.mapper.TemplateMapper;
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
import com.ycwl.basic.model.pc.face.req.FaceReqQuery;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.repository.TemplateRepository;
import com.ycwl.basic.service.pc.FaceService;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.service.task.impl.TaskTaskServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -37,23 +32,21 @@ public class VideoTaskGenerator {
@Autowired
private FaceMapper faceMapper;
@Autowired
private TaskFaceService taskFaceService;
@Autowired
private TemplateBiz templateBiz;
@Autowired
private TaskTaskServiceImpl taskTaskService;
@Autowired
private TemplateMapper templateMapper;
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private ScenicRepository scenicRepository;
@Autowired
private FaceService faceService;
@Scheduled(cron = "0 0 * * * *")
public void generateVideoTask() {
List<ScenicRespVO> scenicList = scenicMapper.list(new ScenicReqQuery());
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
if (scenicList.isEmpty()) {
return;
}
@@ -63,7 +56,7 @@ public class VideoTaskGenerator {
int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
calendar.clear();
scenicList.parallelStream().forEach(scenic -> {
Long scenicId = scenic.getId();
Long scenicId = Long.valueOf(scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig == null) {
log.info("当前景区{},无配置信息", scenic.getName());
@@ -79,11 +72,11 @@ public class VideoTaskGenerator {
if (contentList.isEmpty()) {
return;
}
FaceReqQuery query = new FaceReqQuery();
query.setScenicId(scenicId);
query.setStartTime(DateUtil.beginOfDay(new Date()));
query.setEndTime(DateUtil.endOfDay(new Date()));
List<FaceRespVO> list = faceMapper.list(query);
FaceReqQuery faceReqQuery = new FaceReqQuery();
faceReqQuery.setScenicId(scenicId);
faceReqQuery.setStartTime(DateUtil.beginOfDay(new Date()));
faceReqQuery.setEndTime(DateUtil.endOfDay(new Date()));
List<FaceRespVO> list = faceMapper.list(faceReqQuery);
list.forEach(face -> {
faceService.matchFaceId(face.getId(), false);
if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) {

View File

@@ -1,267 +0,0 @@
<?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.ycwl.basic.mapper.ScenicMapper">
<insert id="add">
insert into scenic(id, `name`, introduction, phone, cover_url, longitude, latitude, radius, province, city, area, address, price, kf_code_url, kf_phone, logo_url, source_video_price, source_image_price)
values (#{id}, #{name}, #{introduction}, #{phone}, #{coverUrl},#{longitude}, #{latitude}, #{radius}, #{province}, #{city}, #{area}, #{address}, #{price}, #{kfCodeUrl}, #{kfPhone}, #{logoUrl}, #{sourceVideoPrice}, #{sourceImagePrice})
</insert>
<insert id="addConfig">
insert into scenic_config(id, scenic_id, create_time)
values (#{id}, #{scenicId}, now())
</insert>
<update id="update">
update
scenic
<set>
<if test="name!=null and name!=''">
`name`=#{name},
</if>
<if test="phone!=null and phone!=''">
`phone`=#{phone},
</if>
<if test="introduction!=null and introduction!=''">
introduction=#{introduction},
</if>
<if test="coverUrl!=null and coverUrl!=''">
cover_url=#{coverUrl},
</if>
<if test="longitude!=null">
longitude=#{longitude},
</if>
<if test="latitude!=null">
latitude=#{latitude},
</if>
<if test="radius!=null">
radius=#{radius},
</if>
<if test="status!=null">
status=#{status},
</if>
<if test="province!=null and province!=''">
province=#{province},
</if>
<if test="city!=null and city!=''">
city=#{city},
</if>
<if test="area!=null and area!=''">
area=#{area},
</if>
<if test="address!=null and address!=''">
address=#{address},
</if>
<if test="kfCodeUrl!=null">
kf_code_url=#{kfCodeUrl},
</if>
<if test="kfPhone!=null">
kf_phone=#{kfPhone},
</if>
<if test="logoUrl!=null">
logo_url=#{logoUrl},
</if>
<if test="price!=null">
price=#{price},
</if>
<if test="sourceVideoPrice!=null">
source_video_price=#{sourceVideoPrice},
</if>
<if test="sourceImagePrice!=null">
source_image_price=#{sourceImagePrice},
</if>
</set>
where id = #{id}
</update>
<update id="updateStatus">
update
scenic
set status = (CASE
status
WHEN 1 THEN
0
WHEN 0 THEN
1
END)
where id = #{id}
</update>
<update id="updateConfigById">
update scenic_config
<set>
<if test="startTime!=null">
start_time=#{startTime},
</if>
<if test="endTime!=null">
end_time=#{endTime},
</if>
<if test="isDefault!=null">
is_default=#{isDefault},
</if>
all_free=#{allFree},
book_routine=#{bookRoutine},
tour_time=#{tourTime},
sample_store_day=#{sampleStoreDay},
face_store_day=#{faceStoreDay},
video_store_day=#{videoStoreDay},
template_new_video_type=#{templateNewVideoType},
anti_screen_record_type=#{antiScreenRecordType},
disable_source_video=#{disableSourceVideo},
disable_source_image=#{disableSourceImage},
video_source_store_day=#{videoSourceStoreDay},
image_source_store_day=#{imageSourceStoreDay},
user_source_expire_day=#{userSourceExpireDay},
face_score_threshold=#{faceScoreThreshold},
force_finish_time=#{forceFinishTime},
face_detect_helper_threshold=#{faceDetectHelperThreshold},
store_type=#{storeType},
store_config_json=#{storeConfigJson},
tmp_store_type=#{tmpStoreType},
tmp_store_config_json=#{tmpStoreConfigJson},
local_store_type=#{localStoreType},
local_store_config_json=#{localStoreConfigJson},
broker_direct_rate=#{brokerDirectRate},
watermark_type=#{watermarkType},
watermark_scenic_text=#{watermarkScenicText},
watermark_dt_format=#{watermarkDtFormat},
face_type=#{faceType},
face_config_json=#{faceConfigJson},
pay_type=#{payType},
pay_config_json=#{payConfigJson},
image_source_pack_hint=#{imageSourcePackHint},
video_source_pack_hint=#{videoSourcePackHint},
extra_notification_time=#{extraNotificationTime},
photo_free_num= #{photoFreeNum},
video_free_num= #{videoFreeNum},
voucher_enable= #{voucherEnable}
</set>
where id = #{id}
</update>
<delete id="deleteById">
delete from scenic where id = #{id}
</delete>
<delete id="deleteConfigByScenicId">
delete from scenic_config where scenic_id = #{scenicId}
</delete>
<select id="list" resultMap="scenic">
select s.id, `name`, `phone`, introduction,logo_url,cover_url, longitude, latitude, radius, province, city, area, address, `status`, s.create_time, update_time, kf_code_url, kf_phone,
s.price, s.source_video_price, s.source_image_price,
(select scenic_account.account from scenic_account where scenic_account.scenic_id = s.id and scenic_account.is_super = 1 limit 1) as account,
s.price
from scenic s
<where>
<if test="name!=null and name!=''">
and locate(#{name},`name`) > 0
</if>
<if test="province!=null and province!=''">
and locate(#{province},`province`) > 0
</if>
<if test="city!=null and city!=''">
and locate(#{city},`city`) > 0
</if>
<if test="area!=null and area!=''">
and locate(#{area},`area`) > 0
</if>
<if test="status!=null">
and `status` = #{status}
</if>
<if test="startTime!=null">
and s.create_time &gt;= #{startTime}
</if>
<if test="endTime!=null">
and s.create_time &lt;= #{endTime}
</if>
</where>
</select>
<select id="getById" resultMap="scenic">
select s.id, `name`, `phone`, introduction, logo_url,cover_url, longitude, latitude, radius, province, city, area, address, `status`, s.create_time, update_time,
s.price, s.source_video_price, s.source_image_price, kf_code_url, kf_phone
from scenic s
where s.id = #{id}
</select>
<select id="appList" resultType="com.ycwl.basic.model.mobile.scenic.ScenicAppVO">
select s.id, `name`, `phone`, introduction, cover_url, longitude, latitude, radius, province, city, area, address,
(SELECT COUNT(1) FROM device WHERE scenic_id = s.id AND status = 1) as deviceNum
from scenic s
where
`status` = 1
<if test="name!=null and name!=''">
and locate(#{name},`name`) > 0
</if>
<if test="province!=null and province!=''">
and locate(#{province},`province`) > 0
</if>
<if test="city!=null and city!=''">
and locate(#{city},`city`) > 0
</if>
<if test="area!=null and area!=''">
and locate(#{area},`area`) > 0
</if>
<if test="startTime!=null">
and s.create_time &gt;= #{startTime}
</if>
<if test="endTime!=null">
and s.create_time &lt;= #{endTime}
</if>
</select>
<select id="getAppById" resultType="com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO">
select s.id, `name`, `phone`, introduction, logo_url,cover_url, longitude, latitude, radius, province, city, area, address, kf_code_url, kf_phone, status
from scenic s
where s.id = #{id}
</select>
<select id="scenicListByLnLa" resultType="com.ycwl.basic.model.mobile.scenic.ScenicAppVO">
select s.id,
`name`,
`phone`,
introduction,
cover_url,
longitude,
latitude,
radius,
province,
city,
area,
address,
(SELECT COUNT(1) FROM device WHERE scenic_id = s.id AND status = 1) as deviceNum,
ifnull(
cast(
ST_Distance_Sphere(
Point(longitude, latitude), Point(#{longitude}, #{latitude})
) AS
DECIMAL(10, 2)
), 0
) AS distance
from scenic s
where `status` = 1
and `latitude` is not null
and `longitude` is not null
ORDER BY distance ASC
</select>
<select id="getConfig" resultType="com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity">
select *
from scenic_config
where scenic_id = #{scenicId}
</select>
<select id="get" resultType="com.ycwl.basic.model.pc.scenic.entity.ScenicEntity">
select *
from scenic
where id = #{id}
</select>
<resultMap id="scenic" type="com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="phone" column="phone"/>
<result property="account" column="account"/>
<result property="introduction" column="introduction"/>
<result property="logoUrl" column="logo_url"/>
<result property="coverUrl" column="cover_url"/>
<result property="longitude" column="longitude"/>
<result property="latitude" column="latitude"/>
<result property="radius" column="radius"/>
<result property="province" column="province"/>
<result property="city" column="city"/>
<result property="area" column="area"/>
<result property="address" column="address"/>
<result property="status" column="status"/>
<result property="price" column="price"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>

View File

@@ -5,9 +5,9 @@ import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.profile.DefaultProfile;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
@@ -41,8 +41,6 @@ public class FaceCleanerTest {
@Autowired
private FaceSampleMapper faceSampleMapper;
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private FaceCleaner faceCleaner;
@Autowired
private ScenicService scenicService;
@@ -51,7 +49,7 @@ public class FaceCleanerTest {
@Test
public void testA() {
ScenicEntity scenic = scenicMapper.get(3980001650692722688L);
ScenicEntity scenic = scenicRepository.getScenic(3980001650692722688L);
log.info("当前景区{},开始删除人脸样本", scenic.getId());
IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(scenic.getId());
int sampleStoreDay = 1;
@@ -79,8 +77,9 @@ public class FaceCleanerTest {
@Test
public void test() {
ScenicReqQuery scenicQuery = new ScenicReqQuery();
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
scenicList.forEach(scenic -> {
log.info("当前景区{},开始删除人脸样本", scenic.getName());
});

View File

@@ -1,12 +1,13 @@
package com.ycwl.basic.task;
import cn.hutool.core.date.DateUtil;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.StatisticsMapper;
import com.ycwl.basic.model.mobile.statistic.req.CommonQueryReq;
import com.ycwl.basic.model.mobile.statistic.resp.AppStatisticsFunnelVO;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppStatisticsService;
import com.ycwl.basic.utils.ApiResponse;
import lombok.extern.slf4j.Slf4j;
@@ -27,11 +28,11 @@ public class ScenicStatsTaskTest {
@Autowired
private ScenicStatsTask task;
@Autowired
private ScenicMapper scenicMapper;
@Autowired
private AppStatisticsService statisticsService;
@Autowired
private StatisticsMapper statisticsMapper;
@Autowired
private ScenicRepository scenicRepository;
@Test
public void testA() {
@@ -42,17 +43,20 @@ public class ScenicStatsTaskTest {
public void testB() {
Calendar calendar = Calendar.getInstance();
calendar.set(2025, Calendar.MAY, 1);
List<ScenicRespVO> list = scenicMapper.list(new ScenicReqQuery());
ScenicReqQuery query = new ScenicReqQuery();
query.setPageSize(1000);
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
while (calendar.getTime().getTime() < System.currentTimeMillis()) {
System.out.println(calendar.getTime());
list.forEach((scenic) -> {
CommonQueryReq query = new CommonQueryReq();
query.setScenicId(scenic.getId());
query.setStartTime(DateUtil.beginOfDay(calendar.getTime()));
query.setEndTime(DateUtil.endOfDay(calendar.getTime()));
ApiResponse<AppStatisticsFunnelVO> resp = statisticsService.userConversionFunnel(query);
scenicList.forEach((scenic) -> {
Long scenicId = Long.valueOf(scenic.getId());
CommonQueryReq commonQueryReq = new CommonQueryReq();
commonQueryReq.setScenicId(scenicId);
commonQueryReq.setStartTime(DateUtil.beginOfDay(calendar.getTime()));
commonQueryReq.setEndTime(DateUtil.endOfDay(calendar.getTime()));
ApiResponse<AppStatisticsFunnelVO> resp = statisticsService.userConversionFunnel(commonQueryReq);
AppStatisticsFunnelVO data = resp.getData();
statisticsMapper.insertStat(scenic.getId(), DateUtil.beginOfDay(calendar.getTime()), data);
statisticsMapper.insertStat(scenicId, DateUtil.beginOfDay(calendar.getTime()), data);
});
calendar.add(Calendar.DAY_OF_MONTH, 1);
}