package com.ylx.project.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ylx.common.core.domain.entity.SysDictData; import com.ylx.common.exception.ServiceException; import com.ylx.common.utils.DateUtils; import com.ylx.common.utils.SecurityUtils; import com.ylx.massage.domain.dto.OptionDTO; import com.ylx.massage.domain.dto.ServiceOptionDTO; import com.ylx.massage.domain.vo.ProductOptionVO; import com.ylx.massage.domain.vo.ProductServiceOptionVO; import com.ylx.massage.service.IMaProjectService; import com.ylx.project.domain.Project; import com.ylx.project.domain.bookMerchant.dto.BookMerchantDTO; import com.ylx.project.domain.bookMerchant.vo.BookMerchantVO; import com.ylx.project.domain.bookMerchant.vo.BookProjectDetailVO; import com.ylx.project.domain.bookMerchant.vo.ProjectInfoVO; import com.ylx.project.domain.dto.ProjectAddDTO; import com.ylx.project.domain.dto.ProjectSearchDTO; import com.ylx.project.domain.dto.ProjectUpdateDTO; import com.ylx.project.domain.vo.ProjectBaseVo; import com.ylx.project.domain.vo.ProjectDetailVo; import com.ylx.project.domain.vo.ProjectPageVo; import com.ylx.project.enums.ProjectStatusEnum; import com.ylx.project.mapper.ProjectMapper; import com.ylx.project.service.ProjectService; import com.ylx.servicecategory.domain.ServiceCategory; import com.ylx.servicecategory.service.ServiceCategoryService; import com.ylx.system.service.ISysDictDataService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Slf4j @Service public class ProjectServiceImpl extends ServiceImpl implements ProjectService { @Resource private ServiceCategoryService serviceCategoryService; @Resource private ISysDictDataService sysDictDataService; @Resource private IMaProjectService maProjectService; @Override public Page list(Page page, ProjectSearchDTO dto) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); // 项目标题 if (StringUtils.isNotBlank(dto.getTitle())) { queryWrapper.like(Project::getTitle, dto.getTitle()); } // 状态 if (ObjectUtil.isNotEmpty(dto.getStatus())) { queryWrapper.eq(Project::getStatus, dto.getStatus()); } // 服务类目ID if (ObjectUtil.isNotEmpty(dto.getCategoryId())) { queryWrapper.eq(Project::getCategoryId, dto.getCategoryId()); } queryWrapper.orderByDesc(Project::getCreateTime).orderByDesc(Project::getSortOrder); Page pageData = new Page<>(); pageData.setCurrent(page.getCurrent()); pageData.setSize(page.getSize()); Page projectPage = this.baseMapper.selectPage(page, queryWrapper); if (ObjectUtil.isNotNull(projectPage) && CollectionUtil.isNotEmpty(projectPage.getRecords())) { List voList = projectPage.getRecords().stream() .map(this::convertToVo) // 抽取转换方法 .collect(Collectors.toList()); pageData.setRecords(voList); pageData.setTotal(projectPage.getTotal()); pageData.setPages(projectPage.getPages()); } return pageData; } @Override @Transactional(rollbackFor = Exception.class) public void edit(ProjectUpdateDTO dto) { Long id = dto.getId(); Project entity = this.getById(id); if (ObjectUtil.isNull(entity)) { throw new IllegalArgumentException("参数有误,项目不存在"); } BeanUtil.copyProperties(dto, entity); entity.setUpdateBy(SecurityUtils.getUsername()); entity.setUpdateTime(DateUtils.getNowDate()); // 根据项目亮点ID集合获取项目亮点 String highlightNames = this.buildHighlightNames(dto.getHighlightIds()); if (StrUtil.isNotEmpty(highlightNames)) { entity.setHighlight(highlightNames); } boolean updateResult = this.updateById(entity); if (!updateResult) { throw new ServiceException("更新项目失败"); } } @Override @Transactional(rollbackFor = Exception.class) public void add(ProjectAddDTO dto) { Project entity = new Project(); ServiceCategory serviceCategoryDetail = this.serviceCategoryService.getServiceCategoryDetail(dto.getCategoryId()); if (ObjectUtil.isNull(serviceCategoryDetail)) { throw new ServiceException("服务类目不存在"); } BeanUtil.copyProperties(dto, entity); entity.setType(serviceCategoryDetail.getServiceTag()); entity.setCreateBy(SecurityUtils.getUsername()); entity.setCreateTime(DateUtils.getNowDate()); // 根据项目亮点ID集合获取项目亮点 String highlightNames = this.buildHighlightNames(dto.getHighlightIds()); if (StrUtil.isNotEmpty(highlightNames)) { entity.setHighlight(highlightNames); } boolean saveResult = this.save(entity); if (!saveResult) { throw new ServiceException("添加项目失败"); } } @Override public ProjectDetailVo getDetailsInfo(Long id) { if (ObjectUtil.isNull(id)) { throw new ServiceException("项目ID不能为空"); } ProjectDetailVo detailVo = this.baseMapper.selectProjectDetailById(id); if (ObjectUtil.isNull(detailVo)) { throw new ServiceException("项目不存在"); } return detailVo; } @Override @Transactional(rollbackFor = Exception.class) public void deleteProjectById(Long id) { if (ObjectUtil.isNull(id)) { throw new ServiceException("项目ID不能为空"); } if (id <= 0) { throw new ServiceException("项目ID不正确"); } log.info("根据主键ID删除项目,ID:{}", id); int deleteResult = this.baseMapper.deleteProjectById(id); if (deleteResult <= 0) { throw new ServiceException("项目不存在或已删除"); } } @Override public IPage selectOptionUnionPage(Page page, OptionDTO dto) { return baseMapper.selectOptionUnionPage(page, dto); } @Override public Page selectServiceOptionsPage(Page page, ServiceOptionDTO dto) { return baseMapper.selectServiceOptionsPage(page, dto); } @Override public List getProjectTabListByCategoryId(Integer categoryId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Project::getCategoryId, categoryId) .eq(Project::getStatus, ProjectStatusEnum.ON_SHELF.getCode()); List projects = this.baseMapper.selectList(wrapper); return BeanUtil.copyToList(projects, ProjectBaseVo.class); } @Override public BookProjectDetailVO getBookingProjectDetail(BookMerchantDTO dto) { BookProjectDetailVO vo = new BookProjectDetailVO(); Long projectId = dto.getProjectId(); // 1. 查询项目基础信息 Project project = this.baseMapper.selectById(projectId); if (ObjectUtil.isNull(project)) { throw new ServiceException("项目不存在"); } if (ObjectUtil.equals(project.getStatus(), ProjectStatusEnum.OFF_SHELF.getCode())) { throw new ServiceException("项目已下架"); } ProjectInfoVO projectInfo = new ProjectInfoVO(); BeanUtil.copyProperties(project, projectInfo); vo.setProjectInfo(projectInfo); // 2. 查询商户列表 Page page = maProjectService.selectMerchantList(new Page<>(dto.getCurrent(), dto.getSize()), dto); // 3.判断数据中的currentPrice为null就设置为projectInfo的price if (ObjectUtil.isNotNull(page) && CollUtil.isNotEmpty(page.getRecords())) { for (BookMerchantVO merchantVO : page.getRecords()) { BigDecimal price = merchantVO.getCurrentPrice(); // 为空 或者 等于0,统一赋值项目原价 if (ObjectUtil.isNull(price) || price.compareTo(BigDecimal.ZERO) == 0) { merchantVO.setCurrentPrice(projectInfo.getPrice()); } } } vo.setMerchantList(page); return vo; } private ProjectPageVo convertToVo(Project entity) { ProjectPageVo vo = new ProjectPageVo(); // 属性拷贝(推荐) BeanUtil.copyProperties(entity, vo); return vo; } /** * 根据亮点ID集合构建高亮名称字符串 * * @param highlightIds 逗号分隔的ID字符串或单个ID * @return 拼接好的名称字符串,如 "技术领先,市场广阔" */ private String buildHighlightNames(String highlightIds) { // 1. 基础校验:如果ID为空,直接返回空字符串,避免后续查库 if (StringUtils.isBlank(highlightIds)) { return ""; } // 2. 解析ID列表 (兼容逗号分隔的情况) List idList = Arrays.asList(highlightIds.split(",")); // 3. 批量查询字典表 List dictList = this.sysDictDataService.list( new QueryWrapper() .in("dict_code", idList) .select("dict_label") // 【性能优化】只查询需要的字段,减少IO开销 ); // 4. 提取名称并拼接 return dictList.stream() .map(SysDictData::getDictLabel) .filter(StringUtils::isNotBlank) // 过滤掉可能为空的标签 .collect(Collectors.joining(",")); } }