Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

19 changed files with 54 additions and 469 deletions

View File

@ -249,18 +249,6 @@ public class CacheConstants {
return ZONE_PROJECT_SORT_BY_SCORE + "*:" + zoneId + ":*";
}
/**
* 专区统计数据缓存前缀
*/
private final static String ZONE_STATISTICS_KEY = "zone:statistics:";
/**
* 获取专区统计数据缓存key
*/
public static String getZoneStatisticsKey(Long zoneId) {
return ZONE_STATISTICS_KEY + zoneId;
}
/**
* 文件打包是否完成0代表未完成1代表已完成-1代表打包失败需要重新打包
*/

View File

@ -1504,17 +1504,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
cmsAsyncService.updateCmsPublishDataByGitLink(cmsProject, cmsDoc, branchName);
}
private int deleteCmsDir(CmsProject cmsProject, CmsDoc cmsDir) {
if (!isNoAuditRequired(cmsDir.getDeptId()) || tokenService.hasDeptPerms(cmsDir.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT)) {
boolean deleteResult = cmsAsyncService.deleteCmsDocForGitLink(cmsDir, cmsProject, CmsConstants.BRANCH_MASTER);
if (deleteResult) {
return cmsDocMapper.deleteCmsDocById(cmsDir.getId());
}
throw new ServiceException("栏目删除失败");
}
throw new ServiceException("无权限删除栏目");
}
@Override
public int deleteCmsDocById(Long id) {
CmsDoc cmsDoc = cmsDocMapper.selectCmsDocById(id);
@ -1524,9 +1513,6 @@ public class CmsDocServiceImpl implements ICmsDocService {
checkCmsLockStatus(cmsDoc.getDeptId());
//2获取专区项目
CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(cmsDoc.getDeptId());
if (cmsDoc.getIsDir()) {
return deleteCmsDir(cmsProject, cmsDoc);
}
//删除待审核审核未通过文章删除临时分支拒绝合并请求
if (DocAuditStatus.TO_BE_AUDIT.getAuditCode().equals(cmsDoc.getAuditStatus())) {

View File

@ -229,7 +229,6 @@
<include refid="selectCmsDocVo"/>
<where>
and name = #{name}
and audit_status != 0
and dept_id = #{deptId}
<choose>
<when test="dirName != null">

View File

@ -1,7 +1,6 @@
package com.microservices.zone.common.controller;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
@ -20,11 +19,8 @@ import com.microservices.zone.detail.service.IZoneDetailService;
import com.microservices.zone.member.domain.vo.ZoneMemberDataVo;
import com.microservices.zone.member.domain.vo.ZoneMemberOpenSearchVo;
import com.microservices.zone.member.domain.vo.ZoneMemberOverviewVo;
import com.microservices.zone.member.domain.vo.ZoneMemberSearchVo;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeCountVo;
import com.microservices.zone.member.domain.vo.ZonePointsTopDocVo;
import com.microservices.zone.member.service.IZoneMemberService;
import com.microservices.zone.member.service.IZoneMemberTypeService;
import com.microservices.zone.member.service.IZonePointsAccountService;
import com.microservices.zone.partners.domain.vo.ZonePartnersOverviewVo;
import com.microservices.zone.partners.service.IZonePartnersService;
@ -79,8 +75,6 @@ public class OpenController extends BaseController {
@Autowired
private IZoneMemberService zoneMemberService;
@Autowired
private IZoneMemberTypeService zoneMemberTypeService;
@Autowired
private IZonePartnersService zonePartnersService;
@Autowired
private IZoneProjectService zoneProjectService;
@ -280,41 +274,6 @@ public class OpenController extends BaseController {
return getGenericsDataTable(list);
}
/**
* 获取特色专区会员分类列表含各分类下已审核会员数量
*/
@GetMapping("/{zoneId}/memberType/list")
@ApiOperation("获取特色专区会员分类列表(含已审核会员数量)")
public GenericsTableDataInfo<ZoneMemberTypeCountVo> memberTypeList(
@ApiParam(name = "zoneId", value = "专区Id", required = true) @PathVariable("zoneId") Long zoneId,
@ApiParam(name = "name", value = "会员分类名称") String name) {
List<ZoneMemberTypeCountVo> list = zoneMemberTypeService.selectZoneMemberTypeListWithCount(zoneId, name);
return getGenericsDataTable(list);
}
/**
* 获取特色专区会员列表仅已审核会员支持名称模糊搜索及分类/等级过滤
*/
@GetMapping("/{zoneId}/member/list")
@ApiOperation("获取特色专区会员列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "当前页码", paramType = "query", dataType = "Integer"),
@ApiImplicitParam(name = "pageSize", value = "每页显示记录数未传默认100", paramType = "query", dataType = "Integer")
})
public GenericsTableDataInfo<ZoneMemberDataVo> memberList(
@ApiParam(name = "zoneId", value = "专区Id", required = true) @PathVariable("zoneId") Long zoneId,
ZoneMemberSearchVo zoneMemberSearchVo,
@RequestParam(value = "pageNum", required = false) Integer pageNum,
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
zoneMemberSearchVo.setZoneId(zoneId);
if (pageNum == null || pageNum < 1) {
pageNum = 1;
}
int effectivePageSize = (pageSize == null || pageSize < 1) ? 100 : pageSize;
PageHelper.startPage(pageNum, effectivePageSize);
return zoneMemberService.selectOpenZoneMemberList(zoneMemberSearchVo);
}
/**
* 检查当前用户是否有该专区的权限
*/

View File

@ -170,11 +170,11 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
* Nthreads =Ncpu*Ucpu*(1+W/C)
*/
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5
2
, 10
, 10
, TimeUnit.SECONDS
, new ArrayBlockingQueue<>(10000)
, new ArrayBlockingQueue<>(100)
, Executors.defaultThreadFactory()
, (r, executor) -> {
throw new ServiceException("【%s】目前创建的人太多了请稍后再试", DateUtils.getNowDate());
@ -485,6 +485,11 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
List<ZoneProject> zoneProjectList = zoneProjectMapper.selectZoneProjectList(zoneProjectSearchVo);
for (ZoneProject zoneProject : zoneProjectList) {
setProjectGitlinkInfoCache(zoneProject);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
logger.error("初始化gitlink项目统计的定时任务延时被中断");
}
}
}
}
@ -536,26 +541,23 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
@Override
public List<JSONObject> getGitlinkProjectsDetail(List<String> gitLinkProjectIdList) {
int total = gitLinkProjectIdList.size();
if (total == 0) {
return new ArrayList<>();
}
// 向上取整分片修复原 size/50+1 在整除时多出一个空分片会发出一次 ids 为空的请求
int queryCount = (total + 49) / 50;
int queryCount = gitLinkProjectIdList.size() / 50 + 1;
CountDownLatch countDownLatch = new CountDownLatch(queryCount);
// 使用线程安全的 ConcurrentLinkedQueue 收集结果修复原 ArrayList 在多线程并发 addAll 下丢数据/越界的隐患
ConcurrentLinkedQueue<JSONObject> gitLinkProjectQueue = new ConcurrentLinkedQueue<>();
List<JSONObject> gitLinkProjectList = new ArrayList<>();
for (int i = 0; i < queryCount; i++) {
int finalI = i;
threadPoolExecutor.execute(() -> {
try {
int pageMaxCount = Math.min((finalI + 1) * 50, total);
int pageMaxCount = (finalI + 1) * 50;
if (pageMaxCount >= gitLinkProjectIdList.size()) {
pageMaxCount = gitLinkProjectIdList.size();
}
List<String> tmpIdList = gitLinkProjectIdList.subList(finalI * 50, pageMaxCount);
JSONObject result = gitLinkRequestHelper.doGet(
ZoneGitLinkRequestUrl.PROJECTS("?ids=" + String.join(ZoneConstants.ARRAY_SPLIT_SYMBOLS, tmpIdList))
);
gitLinkProjectQueue.addAll(result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class));
gitLinkProjectList.addAll(result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class));
} catch (Exception e) {
logger.error("异步批量获取项目详细信息失败:{}", e.getMessage());
} finally {
@ -569,7 +571,7 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
logger.error("根据gitlinkProjectId调用Gitlink接口批量获取项目详细信息失败{}", e.getMessage());
throw new ServiceException("获取平台项目详细信息失败");
}
return new ArrayList<>(gitLinkProjectQueue);
return gitLinkProjectList;
}
private Double calcProjectScore(ZoneProject zoneProject, String startDate, String endDate) {

View File

@ -237,14 +237,6 @@ public interface IZoneDetailService {
ZoneStatisticsVo getZoneStatistics(Long zoneId);
/**
* 计算专区统计数据内部方法用于定时任务调用
*
* @param zoneId 专区ID
* @return 统计数据
*/
ZoneStatisticsVo calculateZoneStatistics(Long zoneId);
/**
* 判断专区是否为积分专区
*

View File

@ -56,7 +56,6 @@ import com.microservices.zone.resource.mapper.ZoneResourceTypeMapper;
import com.microservices.zone.specialProject.domain.ZoneSpecialProject;
import com.microservices.zone.specialProject.service.IZoneSpecialProjectService;
import com.microservices.zone.utils.ZoneConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
@ -68,7 +67,6 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -78,7 +76,6 @@ import java.util.stream.Collectors;
* @date 2023-05-09
*/
@Service
@Slf4j
public class ZoneDetailServiceImpl implements IZoneDetailService {
@Autowired
private ZoneDetailMapper zoneDetailMapper;
@ -920,7 +917,7 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
}
@Override
public ZoneStatisticsVo calculateZoneStatistics(Long zoneId) {
public ZoneStatisticsVo getZoneStatistics(Long zoneId) {
ZoneStatisticsVo zoneStatisticsVo = new ZoneStatisticsVo();
ZoneDetail zoneDetail = zoneDetailMapper.selectZoneDetailById(zoneId);
@ -985,35 +982,6 @@ public class ZoneDetailServiceImpl implements IZoneDetailService {
return zoneStatisticsVo;
}
@Override
public ZoneStatisticsVo getZoneStatistics(Long zoneId) {
String cacheKey = CacheConstants.getZoneStatisticsKey(zoneId);
try {
// 1. 尝试从Redis缓存获取
ZoneStatisticsVo cachedStatistics = redisService.getCacheObject(cacheKey);
if (cachedStatistics != null) {
log.debug("专区[{}]统计数据来自缓存", zoneId);
return cachedStatistics;
}
} catch (Exception e) {
log.warn("专区[{}]统计数据缓存读取失败,执行降级逻辑", zoneId, e);
}
// 2. 缓存异常或未命中执行实时计算
log.info("专区[{}]统计数据缓存未命中,执行实时计算", zoneId);
ZoneStatisticsVo statistics = calculateZoneStatistics(zoneId);
// 3. 尝试缓存计算结果失败不影响主流程
try {
redisService.setCacheObject(cacheKey, statistics, 7200L, TimeUnit.SECONDS);
} catch (Exception e) {
log.warn("专区[{}]统计数据缓存写入失败", zoneId, e);
}
return statistics;
}
@Override
public boolean isPointsZone(Long zoneId) {
ZoneDetail zoneDetail = zoneDetailMapper.selectZoneDetailById(zoneId);

View File

@ -21,6 +21,4 @@ public class ZoneMemberWithScore extends ZoneMember implements Serializable {
private Double searchScore;
private String memberTypeName;
private String memberLevelName;
}

View File

@ -1,25 +0,0 @@
package com.microservices.zone.member.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 专区会员分类含已审核会员数量对象
*
* @author otto
*/
@Data
@ApiModel("专区会员分类(含已审核会员数量)对象")
public class ZoneMemberTypeCountVo {
@ApiModelProperty(value = "专区会员分类Id")
private Long id;
@ApiModelProperty(value = "专区会员分类名称")
private String name;
@ApiModelProperty(value = "专区会员分类简介")
private String introduction;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "已审核会员数量")
private Long memberCount;
}

View File

@ -2,7 +2,6 @@ package com.microservices.zone.member.mapper;
import com.microservices.zone.member.domain.ZoneMember;
import com.microservices.zone.member.domain.vo.ZoneMemberSearchVo;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeCountVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -122,14 +121,6 @@ public interface ZoneMemberMapper {
*/
Integer selectCountByZoneId(ZoneMember zoneMember);
/**
* 按会员分类统计专区下已审核会员数量
*
* @param zoneId 专区Id
* @return 每个分类id对应的已审核会员数量
*/
List<ZoneMemberTypeCountVo> selectAuditedMemberCountByType(@Param("zoneId") Long zoneId);
/**
* 获取指定序号的会员
*
@ -199,28 +190,4 @@ public interface ZoneMemberMapper {
@Param("pageSize") int pageSize);
Long globalSearchCount(@Param("keyword") String keyword, @Param("zoneId") Long zoneId);
/**
* 全局搜索 - 扩展模糊搜索含会员分类和等级
*
* @param keyword 搜索关键词
* @param zoneId 专区ID
* @param offset 偏移量
* @param pageSize 每页数量
* @return 搜索结果列表含评分
*/
List<com.microservices.zone.member.domain.ZoneMemberWithScore> globalSearchWithScoreExtended(
@Param("keyword") String keyword,
@Param("zoneId") Long zoneId,
@Param("offset") int offset,
@Param("pageSize") int pageSize);
/**
* 全局搜索 - 扩展模糊搜索计数含会员分类和等级
*
* @param keyword 搜索关键词
* @param zoneId 专区ID
* @return 匹配总数
*/
Long globalSearchCountExtended(@Param("keyword") String keyword, @Param("zoneId") Long zoneId);
}

View File

@ -31,14 +31,6 @@ public interface IZoneMemberService {
*/
public GenericsTableDataInfo<ZoneMemberDetailVo> selectZoneMemberList(ZoneMemberSearchVo zoneMemberSearchVo, boolean isOpen);
/**
* 查询特色专区已审核会员列表公开接口不分页由调用方通过 PageHelper 控制
*
* @param zoneMemberSearchVo 特色专区会员查询对象zoneIdnamememberTypeIdmemberLevelId
* @return 特色专区会员集合
*/
public GenericsTableDataInfo<ZoneMemberDataVo> selectOpenZoneMemberList(ZoneMemberSearchVo zoneMemberSearchVo);
/**
* 新增特色专区会员
*

View File

@ -1,7 +1,6 @@
package com.microservices.zone.member.service;
import com.microservices.zone.member.domain.ZoneMemberType;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeCountVo;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeUpdateVo;
import java.util.List;
@ -29,15 +28,6 @@ public interface IZoneMemberTypeService {
*/
public List<ZoneMemberType> selectZoneMemberTypeList(ZoneMemberType zoneMemberType);
/**
* 查询特色专区会员分类列表含各分类下已审核会员数量
*
* @param zoneId 专区Id
* @param name 会员分类名称模糊搜索可为空
* @return 会员分类集合含已审核会员数量
*/
public List<ZoneMemberTypeCountVo> selectZoneMemberTypeListWithCount(Long zoneId, String name);
/**
* 新增特色专区会员分类
*

View File

@ -129,26 +129,6 @@ public class ZoneMemberServiceImpl implements IZoneMemberService {
return PageUtils.toPage(zoneMemberList, this::toZoneMemberDetailVo);
}
/**
* 查询特色专区已审核会员列表公开接口
* 不做数据范围过滤分页由调用方通过 PageHelper 设置
*
* @param zoneMemberSearchVo 特色专区会员查询对象
* @return 特色专区会员集合
*/
@Override
public GenericsTableDataInfo<ZoneMemberDataVo> selectOpenZoneMemberList(ZoneMemberSearchVo zoneMemberSearchVo) {
zoneMemberSearchVo.setIsAudit(ZoneConstants.MEMBER_AUDIT_PASS);
zoneMemberSearchVo.setIsOpen(true);
List<ZoneMember> zoneMemberList = zoneMemberMapper.selectZoneMemberList(zoneMemberSearchVo);
return PageUtils.toPage(zoneMemberList, this::toOpenZoneMemberDataVo);
}
private ZoneMemberDataVo toOpenZoneMemberDataVo(ZoneMember zoneMember) {
String login = zoneMember.getSysUser() != null ? zoneMember.getSysUser().getUserName() : null;
return zoneMember.toZoneMemberDataVo(login);
}
private ZoneMemberDetailVo toZoneMemberDetailVo(ZoneMember zoneMember) {
ZoneMemberDetailVo zoneMemberDetailVo = new ZoneMemberDetailVo();
BeanUtils.copyProperties(zoneMember, zoneMemberDetailVo);

View File

@ -10,7 +10,6 @@ import com.microservices.zone.detail.service.IZoneDetailService;
import com.microservices.zone.member.domain.ZoneMember;
import com.microservices.zone.member.domain.ZoneMemberType;
import com.microservices.zone.member.domain.vo.ZoneMemberSearchVo;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeCountVo;
import com.microservices.zone.member.domain.vo.ZoneMemberTypeUpdateVo;
import com.microservices.zone.member.mapper.ZoneMemberMapper;
import com.microservices.zone.member.mapper.ZoneMemberTypeMapper;
@ -21,9 +20,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -70,37 +67,6 @@ public class ZoneMemberTypeServiceImpl implements IZoneMemberTypeService {
return zoneMemberTypeMapper.selectZoneMemberTypeList(zoneMemberType);
}
/**
* 查询特色专区会员分类列表含各分类下已审核会员数量
*
* @param zoneId 专区Id
* @param name 会员分类名称模糊搜索可为空
* @return 会员分类集合含已审核会员数量
*/
@Override
public List<ZoneMemberTypeCountVo> selectZoneMemberTypeListWithCount(Long zoneId, String name) {
ZoneMemberType query = new ZoneMemberType();
query.setZoneId(zoneId);
query.setName(name);
List<ZoneMemberType> zoneMemberTypeList = zoneMemberTypeMapper.selectZoneMemberTypeList(query);
if (zoneMemberTypeList == null || zoneMemberTypeList.isEmpty()) {
return new ArrayList<>();
}
Map<Long, Long> countMap = zoneMemberMapper.selectAuditedMemberCountByType(zoneId).stream()
.collect(Collectors.toMap(ZoneMemberTypeCountVo::getId, ZoneMemberTypeCountVo::getMemberCount));
List<ZoneMemberTypeCountVo> result = new ArrayList<>(zoneMemberTypeList.size());
for (ZoneMemberType zoneMemberType : zoneMemberTypeList) {
ZoneMemberTypeCountVo vo = new ZoneMemberTypeCountVo();
vo.setId(zoneMemberType.getId());
vo.setName(zoneMemberType.getName());
vo.setIntroduction(zoneMemberType.getIntroduction());
vo.setSort(zoneMemberType.getSort());
vo.setMemberCount(countMap.getOrDefault(zoneMemberType.getId(), 0L));
result.add(vo);
}
return result;
}
/**
* 新增特色专区会员类别
*

View File

@ -128,51 +128,44 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
@Override
public List<ZoneProjectDataVo> toZoneProjectDataVoList(List<ZoneProject> zoneProjectList) {
if (zoneProjectList.isEmpty()) {
return new ArrayList<>();
}
List<ZoneProjectDataVo> zoneProjectDataVoList = new ArrayList<>();
// 原方案为遍历项目聚合再逐一从GitLink获取对应项目详情此方案延时过高调整为根据项目Id批量获取GitLink项目信息
List<String> gitLinkProjectIdList = zoneProjectList
.stream()
.map(x -> String.valueOf(x.getGitlinkProjectId()))
.collect(Collectors.toList());
List<JSONObject> gitLinkProjectList = zoneAsyncService.getGitlinkProjectsDetail(gitLinkProjectIdList);
// 性能优化整页 zoneId 恒定getGitlinkProjectKeys(每次2次DB) 与字典缓存(每次1次Redis) 提到循环外整页只查一次
String[] projectKeys = getGitlinkProjectKeys(zoneProjectList.get(0).getZoneId());
List<SysDictData> sysDictDataList = DictUtils.getDictCache(CacheConstants.SYS_DICT_GITLINK_PROJECT_PROPERTIES);
// 性能优化构建索引Map将原本逐项 O(N²) stream 过滤改为 O(1) 查表
Map<Long, JSONObject> gitLinkByProjectId = new HashMap<>(gitLinkProjectList.size() * 2);
Set<String> returnedGitLinkIds = new HashSet<>(gitLinkProjectList.size() * 2);
for (JSONObject jp : gitLinkProjectList) {
gitLinkByProjectId.put(jp.getLong("id"), jp);
returnedGitLinkIds.add(jp.getString("id"));
}
List<String> resultGitLinkProjectIdList = gitLinkProjectList
.stream()
.map(x -> x.getString("id"))
.collect(Collectors.toList());
//检查查询的GitLink项目Id列表和需查询的项目Id列表是否一致不一致需要考虑是否该项目在GitLink中设置为私有或者删除了此时需要清理该项目
//直接遍历zoneProject按gitlinkId查Set替代原本逐项的stream过滤删除时仅记录id并在富化循环中跳过不原地修改zoneProjectList以免影响外层PageHelper的分页total统计
Set<Long> removedProjectIds = new HashSet<>();
for (ZoneProject zp : zoneProjectList) {
if (returnedGitLinkIds.contains(String.valueOf(zp.getGitlinkProjectId()))) {
continue;
gitLinkProjectIdList.removeAll(resultGitLinkProjectIdList);
if (!gitLinkProjectIdList.isEmpty()) {
for (String gitLinkProjectId : gitLinkProjectIdList) {
Long projectId = zoneProjectList
.stream()
.filter(x -> gitLinkProjectId.equals(String.valueOf(x.getGitlinkProjectId())))
.map(ZoneProject::getId)
.findFirst().orElse(null);
if (projectId == null) {
throw new ServiceException("该GitLink项目对应的项目聚合不存在(GitLink项目Id[" + gitLinkProjectId + "])");
}
logger.info("GitLink中未查找到对应项目(GitLink项目Id为{}),对该项目进行删除(项目Id为{})"
, gitLinkProjectId
, projectId);
deleteZoneProjectById(projectId);
zoneProjectList = zoneProjectList.stream().filter(x -> !x.getId().equals(projectId)).collect(Collectors.toList());
}
if (removedProjectIds.contains(zp.getId())) {
continue;
}
logger.info("GitLink中未查找到对应项目(GitLink项目Id为{}),对该项目进行删除(项目Id为{})"
, zp.getGitlinkProjectId()
, zp.getId());
deleteZoneProjectById(zp.getId());
removedProjectIds.add(zp.getId());
}
List<ZoneProjectDataVo> zoneProjectDataVoList = new ArrayList<>(zoneProjectList.size());
for (ZoneProject zoneProject : zoneProjectList) {
if (removedProjectIds.contains(zoneProject.getId())) {
continue;
}
JSONObject gitLinkProject = gitLinkByProjectId.get(zoneProject.getGitlinkProjectId());
JSONObject gitLinkProject = gitLinkProjectList
.stream()
.filter(x -> zoneProject.getGitlinkProjectId().equals(x.getLong("id")))
.findFirst()
.orElse(null);
if (gitLinkProject == null) {
throw new ServiceException("该项目聚合对应的GitLink项目不存在(项目Id[" + zoneProject.getId() + "])");
}
@ -186,7 +179,7 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
zoneProjectMapper.updateZoneProject(zoneProject);
}
}
zoneProjectDataVoList.add(zoneProjectToZoneProjectDataVo(zoneProject, gitLinkProject, projectKeys, sysDictDataList));
zoneProjectDataVoList.add(zoneProjectToZoneProjectDataVo(zoneProject, gitLinkProject));
}
return zoneProjectDataVoList;
}
@ -241,16 +234,6 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
}
private ZoneProjectDataVo zoneProjectToZoneProjectDataVo(ZoneProject zoneProject, JSONObject gitLinkProject) {
// 单项查询路径 selectZoneProjectDataById在此计算 keys 与字典再委托给 4 参重载
return zoneProjectToZoneProjectDataVo(
zoneProject,
gitLinkProject,
getGitlinkProjectKeys(zoneProject.getZoneId()),
DictUtils.getDictCache(CacheConstants.SYS_DICT_GITLINK_PROJECT_PROPERTIES));
}
private ZoneProjectDataVo zoneProjectToZoneProjectDataVo(ZoneProject zoneProject, JSONObject gitLinkProject,
String[] projectKeys, List<SysDictData> sysDictDataList) {
//每次从GitLink查询项目时自动更新项目名称和项目标识
updateProjectNameAndFullName(gitLinkProject, zoneProject);
ZoneProjectDataVo zoneProjectDataVo = zoneProject.toZoneProjectDataVo();
@ -279,7 +262,9 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
projectPropertiesVo.put("description", description);
projectKeyName.put("description", "项目简介");
//当专区设置的项目需展示的Key时通过Key获取值否则默认获取相关值projectKeys sysDictDataList 已由调用方按页预算并传入避免逐项查询
String[] projectKeys = getGitlinkProjectKeys(zoneProject.getZoneId());
//当专区设置的项目需展示的Key时通过Key获取值否则默认获取相关值
List<SysDictData> sysDictDataList = DictUtils.getDictCache(CacheConstants.SYS_DICT_GITLINK_PROJECT_PROPERTIES);
if (sysDictDataList != null) {
for (String projectKey : projectKeys) {
SysDictData sysDictData = sysDictDataList.stream().filter(x -> projectKey.equals(x.getDictValue())).findFirst().orElse(null);

View File

@ -52,6 +52,6 @@ public class GlobalSearchRequest implements Serializable {
private Integer pageSize = 20;
@ApiModelProperty(value = "额外搜索参数(1. 项目搜索可传入projectTypeId搜索项目分裂传入topic搜索项目标签2. 会员搜索传入supportMemberCategoryLevelSearch值为true可支持通过关键词模糊搜索会员分类和会员等级")
@ApiModelProperty(value = "额外搜索参数(项目类型projectTypeId,topic")
private JSONObject extraSearchParam;
}

View File

@ -117,23 +117,8 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
if (searchTypes.contains("member")) {
List<GlobalSearchResult> memberResults = searchZoneMembers(request);
allResults.addAll(memberResults);
// 检查是否启用扩展搜索支持会员分类和等级模糊搜索
boolean supportMemberCategoryLevelSearch = false;
if (request.getExtraSearchParam() != null
&& request.getExtraSearchParam().containsKey("supportMemberCategoryLevelSearch")) {
supportMemberCategoryLevelSearch = request.getExtraSearchParam()
.getBoolean("supportMemberCategoryLevelSearch");
}
Long searchMemberCount;
if (supportMemberCategoryLevelSearch) {
searchMemberCount = zoneMemberMapper.globalSearchCountExtended(request.getKeyword(), request.getZoneId());
} else {
searchMemberCount = zoneMemberMapper.globalSearchCount(request.getKeyword(), request.getZoneId());
}
Long searchMemberCount = zoneMemberMapper.globalSearchCount(request.getKeyword(), request.getZoneId());
typeCounts.put("member", searchMemberCount);
searchTotal += searchMemberCount;
}
@ -362,31 +347,12 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
private List<GlobalSearchResult> searchZoneMembers(GlobalSearchRequest request) {
List<GlobalSearchResult> results = new ArrayList<>();
try {
// 检查是否启用扩展搜索支持会员分类和等级模糊搜索
boolean supportMemberCategoryLevelSearch = false;
if (request.getExtraSearchParam() != null
&& request.getExtraSearchParam().containsKey("supportMemberCategoryLevelSearch")) {
supportMemberCategoryLevelSearch = request.getExtraSearchParam()
.getBoolean("supportMemberCategoryLevelSearch");
}
int offset = (request.getPageNum() - 1) * request.getPageSize();
List<ZoneMemberWithScore> members;
if (supportMemberCategoryLevelSearch) {
members = zoneMemberMapper.globalSearchWithScoreExtended(
request.getKeyword(),
request.getZoneId(),
offset,
request.getPageSize()
);
} else {
members = zoneMemberMapper.globalSearchWithScore(
request.getKeyword(),
request.getZoneId(),
offset,
request.getPageSize()
);
}
List<ZoneMemberWithScore> members = zoneMemberMapper.globalSearchWithScore(
request.getKeyword(),
request.getZoneId(),
(request.getPageNum() - 1) * request.getPageSize(),
request.getPageSize()
);
for (ZoneMemberWithScore member : members) {
GlobalSearchResult result = new GlobalSearchResult();
@ -428,9 +394,6 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
if (StringUtils.isNotEmpty(member.getMemberTypeName())) {
extendData.put("memberTypeName", member.getMemberTypeName());
}
if (StringUtils.isNotEmpty(member.getMemberLevelName())) {
extendData.put("memberLevelName", member.getMemberLevelName());
}
if (member.getSysUser() != null) {
extendData.put("username", member.getSysUser().getUserName());
}

View File

@ -1,81 +0,0 @@
package com.microservices.zone.task;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.redis.service.RedisService;
import com.microservices.zone.detail.domain.vo.ZoneBaseDataVo;
import com.microservices.zone.detail.service.IZoneDetailService;
import com.microservices.zone.project.domain.vo.ZoneStatisticsVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 专区统计数据预计算定时任务
*/
@Component
public class ZoneStatisticsJob {
private static final Logger logger = LoggerFactory.getLogger(ZoneStatisticsJob.class);
@Autowired
private IZoneDetailService zoneDetailService;
@Autowired
private RedisService redisService;
/**
* 应用启动时执行专区统计数据预计算
* 确保服务启动后接口立即可用
*/
@PostConstruct
public void initZoneStatistics() {
logger.info("应用启动,执行专区统计数据初始化");
calculateZoneStatistics();
}
/**
* 每小时执行一次专区统计数据预计算
* cron表达式: 每小时的第5分钟执行
*/
@Scheduled(cron = "0 5 * * * ?")
public void calculateZoneStatistics() {
logger.info("开始执行专区统计数据预计算任务");
try {
// 获取所有已发布的专区列表
List<ZoneBaseDataVo> zoneList = zoneDetailService.selectPublishedZoneBaseList();
logger.info("发现已发布专区数量: {}", zoneList.size());
int successCount = 0;
int failCount = 0;
for (ZoneBaseDataVo zone : zoneList) {
try {
// 计算单个专区的统计数据
ZoneStatisticsVo statistics = zoneDetailService.calculateZoneStatistics(zone.getId());
// 存储到Redis缓存
String cacheKey = CacheConstants.getZoneStatisticsKey(zone.getId());
redisService.setCacheObject(cacheKey, statistics, 7200L, TimeUnit.SECONDS);
successCount++;
logger.debug("专区[{}]统计数据计算完成", zone.getId());
} catch (Exception e) {
failCount++;
logger.error("专区[{}]统计数据计算失败", zone.getId(), e);
}
}
logger.info("专区统计数据预计算任务完成 - 成功: {}, 失败: {}", successCount, failCount);
} catch (Exception e) {
logger.error("专区统计数据预计算任务执行失败", e);
}
}
}

View File

@ -105,7 +105,6 @@
id="ZoneMemberWithScoreResult" extends="ZoneMemberResult">
<result property="searchScore" column="search_score"/>
<result property="memberTypeName" column="typeName"/>
<result property="memberLevelName" column="levelName"/>
</resultMap>
<sql id="selectZoneMemberAliasVo">
@ -369,14 +368,6 @@
and zm.member_type_id = #{memberTypeId}
and zm.member_level_id = #{memberLevelId}
</select>
<select id="selectAuditedMemberCountByType"
resultType="com.microservices.zone.member.domain.vo.ZoneMemberTypeCountVo">
select member_type_id as id, count(0) as memberCount
from zone_member
where zone_id = #{zoneId}
and is_audit = '1'
group by member_type_id
</select>
<select id="selectZoneMemberByOrderAndZoneId" resultMap="ZoneMemberResult">
<include refid="selectZoneMemberVo"/>
where zone_id=#{zoneMember.zoneId}
@ -543,39 +534,4 @@
OR u.user_name LIKE CONCAT('%', #{keyword}, '%')
)
</select>
<!-- 全局搜索 - 扩展模糊搜索(含会员分类和等级) -->
<select id="globalSearchWithScoreExtended" resultMap="ZoneMemberWithScoreResult">
<include refid="selectZoneMemberWithSearchVo"/>
WHERE zm.zone_id = #{zoneId}
AND zm.is_audit = '1'
AND zm.del_flag = '0'
AND (
MATCH(zm.name) AGAINST(#{keyword} IN BOOLEAN MODE)
OR zm.name LIKE CONCAT('%', #{keyword}, '%')
OR u.user_name LIKE CONCAT('%', #{keyword}, '%')
OR zmt.name LIKE CONCAT('%', #{keyword}, '%')
OR zml.name LIKE CONCAT('%', #{keyword}, '%')
)
ORDER BY search_score DESC, zm.create_time DESC
LIMIT #{offset}, #{pageSize}
</select>
<select id="globalSearchCountExtended" resultType="java.lang.Long">
SELECT COUNT(*)
FROM zone_member zm
left join sys_user u on u.user_id = zm.user_id
left join zone_member_level zml on zml.id = zm.member_level_id
left join zone_member_type zmt on zmt.id = zm.member_type_id
WHERE zm.zone_id = #{zoneId}
AND zm.is_audit = '1'
AND zm.del_flag = '0'
AND (
MATCH(zm.name) AGAINST(#{keyword} IN BOOLEAN MODE)
OR zm.name LIKE CONCAT('%', #{keyword}, '%')
OR u.user_name LIKE CONCAT('%', #{keyword}, '%')
OR zmt.name LIKE CONCAT('%', #{keyword}, '%')
OR zml.name LIKE CONCAT('%', #{keyword}, '%')
)
</select>
</mapper>