package com.yunhai.cms.service.impl; import com.yunhai.cms.entity.CmsCategory; import com.yunhai.cms.entity.CmsPerson; import com.yunhai.cms.event.SiteContentChangedEvent; import com.yunhai.cms.model.dto.DeleteRequest; import com.yunhai.cms.model.dto.PersonSaveRequest; import com.yunhai.cms.model.vo.PersonVo; import com.yunhai.cms.repository.CmsCategoryRepository; import com.yunhai.cms.repository.CmsPersonRepository; import com.yunhai.platform.apistd.BizException; import com.yunhai.platform.utils.exception.ErrorCode; import com.yunhai.platform.utils.model.BoaUser; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.List; import java.util.stream.Collectors; /** * 名师风采人物管理(docs/20 D-7):站点级 CRUD + people 区块数据源。 * 头像附件引用走 scene=person(B2 模型);categoryId 须属于本站点(防跨站注入)。 */ @Service @RequiredArgsConstructor public class PersonService { private final CmsPersonRepository personRepository; private final CmsCategoryRepository categoryRepository; private final SiteService siteService; private final AttachmentService attachmentService; private final ApplicationEventPublisher eventPublisher; public List list(BoaUser user, Integer siteId) { siteService.requireManageable(user, siteId); return personRepository.findBySiteIdOrderBySortNoAscIdAsc(siteId).stream() .map(PersonVo::of) .collect(Collectors.toList()); } @Transactional public PersonVo save(BoaUser user, PersonSaveRequest req) { siteService.requireManageable(user, req.getSiteId()); if (req.getCategoryId() != null) { CmsCategory category = categoryRepository.findById(req.getCategoryId()) .orElseThrow(() -> new BizException(ErrorCode.PARAM_ERROR, "所属栏目不存在")); if (!category.getSiteId().equals(req.getSiteId())) { throw new BizException(ErrorCode.PARAM_ERROR, "所属栏目不属于本站点"); } } CmsPerson person; if (req.getId() == null) { person = new CmsPerson(); person.setSiteId(req.getSiteId()); } else { person = personRepository.findById(req.getId()) .orElseThrow(() -> new BizException(ErrorCode.PARAM_ERROR, "人物不存在")); if (!person.getSiteId().equals(req.getSiteId())) { throw new BizException(ErrorCode.FORBIDDEN, "无权修改该人物"); } } person.setName(req.getName()); person.setTitle(req.getTitle()); person.setBio(req.getBio()); person.setAvatar(req.getAvatar()); person.setCategoryId(req.getCategoryId()); person.setSortNo(req.getSortNo() == null ? 0 : req.getSortNo()); person.setStatus(req.getStatus() == null ? 1 : req.getStatus()); person = personRepository.save(person); // B2 附件引用:先解引用再回写新头像(编辑换图时旧图回未使用);幂等 attachmentService.release("person", person.getId()); if (StringUtils.hasText(req.getAvatar())) { attachmentService.markUsed(req.getSiteId(), req.getAvatar(), "person", person.getId()); } eventPublisher.publishEvent(new SiteContentChangedEvent(req.getSiteId(), "person")); return PersonVo.of(person); } @Transactional public void delete(BoaUser user, DeleteRequest req) { CmsPerson person = personRepository.findById(req.getId()) .orElseThrow(() -> new BizException(ErrorCode.PARAM_ERROR, "人物不存在")); siteService.requireManageable(user, req.getSiteId()); if (!person.getSiteId().equals(req.getSiteId())) { throw new BizException(ErrorCode.FORBIDDEN, "无权删除该人物"); } personRepository.delete(person); attachmentService.release("person", person.getId()); eventPublisher.publishEvent(new SiteContentChangedEvent(req.getSiteId(), "person")); } }