refactor: 根包由 com.bestsch.bschclassmanage 重命名为 com.yunhai.bschclassmanage

- git mv src/main/java/com/bestsch/bschclassmanage -> src/main/java/com/yunhai/bschclassmanage
- 255 个 Java 文件的 package/import 同步替换为 com.yunhai.bschclassmanage
- pom.xml 项目 groupId 设为 com.yunhai(与外部依赖 com.bestsch:bsch-* 无关,未改动)
- IDE 缓存 workspace.xml 路径同步更新(外部依赖坐标 com.bestsch:bsch-* 保持不动)
This commit is contained in:
Allen
2026-08-12 17:21:22 +08:00
parent 66cd0f1515
commit dc217ca7a9
258 changed files with 1082 additions and 1067 deletions
@@ -0,0 +1,245 @@
package com.yunhai.bschclassmanage.service.impl;
import com.alibaba.fastjson.JSON;
import com.yunhai.bschclassmanage.Repository.SchClassRepository;
import com.yunhai.bschclassmanage.Repository.SchDicCampusRepository;
import com.yunhai.bschclassmanage.annotation.OperationLog;
import com.yunhai.bschclassmanage.entity.SchDicCampus;
import com.yunhai.bschclassmanage.model.constant.LogModule;
import com.yunhai.bschclassmanage.model.entityField.EntityFieldNames;
import com.yunhai.bschclassmanage.model.vo.SelectIntVO;
import com.yunhai.bschclassmanage.service.ISchDicCampusService;
import com.yunhai.bschclassmanage.utils.*;
import com.yunhai.platform.utils.exception.DException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Slf4j
@Service
public class SchDicCampusService implements ISchDicCampusService {
@Autowired
private SchDicCampusRepository schDicCampusRepository;
@Autowired
private SchClassRepository schClassRepository;
@Autowired
private RedisUtil redisUtil;
public List<SchDicCampus> getSchDicCampusList(Integer schId) {
Specification<SchDicCampus> spec = (root, query, cb) -> {
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(root.get(EntityFieldNames.schId), schId));
return cb.and(predicates.toArray(new Predicate[0]));
};
return schDicCampusRepository.findAll(spec);
}
// 获取学校院校列表(带缓存)
public List<SchDicCampus> getSchDicCampusCacheList(Integer schId) {
String cacheKey = RedisConstants.SCHOOL_CAMPUS + "_" + schId;
if (redisUtil.hasKey(cacheKey)) {
// 注意:返回副本或不可变列表,避免外部修改影响缓存
return redisUtil.getList(cacheKey,SchDicCampus.class);
}
// 同步查询数据库,防止缓存击穿
synchronized (this) {
if (redisUtil.hasKey(cacheKey)) {
return redisUtil.getList(cacheKey,SchDicCampus.class);
}
List<SchDicCampus> list = getSchDicCampusList(schId);
// 根据 sort 字段升序排序,null 值排在最后
list.sort(Comparator.comparing(SchDicCampus::getSort,
Comparator.nullsLast(Comparator.naturalOrder())));
redisUtil.set(cacheKey, new ArrayList<>(list), RedisConstants.CACHE_EXPIRE_30D);
return list;
}
}
@OperationLog(module = LogModule.CAMPUS)
@Transactional(rollbackFor = Exception.class)
public void saveSchCampus(UserContext.UserInfo user, SchDicCampus entity) {
Integer schId=user.getSchId();
boolean isNew=entity.getId() == null || entity.getId() == 0;
// 参数校验
if (entity.getName() == null || entity.getName().trim().isEmpty())
throw new IllegalArgumentException("校区名称不能为空");
boolean nameExists;
SchDicCampus oldEntity=null;
if (isNew) {
// 新增:检查同名校区
nameExists = schDicCampusRepository.existsBySchIdAndName(schId, entity.getName());
if (nameExists) {
throw new IllegalArgumentException("校区名称已存在:" + entity.getName());
}
OtherUtil.setBaseEntityValue(user, entity);
schDicCampusRepository.save(entity);
} else {
// 更新:排除自身,检查其他校区同名
nameExists = schDicCampusRepository.existsBySchIdAndNameAndIdNot(schId, entity.getName(), entity.getId());
if (nameExists) {
throw new IllegalArgumentException("校区名称已存在:" + entity.getName());
}
Integer entityId=entity.getId();
SchDicCampus existing = schDicCampusRepository.findById(entityId)
.orElseThrow(() -> new IllegalArgumentException("校区不存在,ID=" + entityId));
oldEntity=OtherUtil.deepCopy(existing,SchDicCampus.class);
OtherUtil.setBaseEntityValue(user, entity);
BeanUtils.copyProperties(entity, existing,
EntityFieldNames.id,
EntityFieldNames.schId,
EntityFieldNames.code,
EntityFieldNames.createDate,
EntityFieldNames.createUserId);
entity=schDicCampusRepository.save(existing);
}
// 清除缓存
String cacheKey = RedisConstants.SCHOOL_CAMPUS + "_" + schId;
redisUtil.del(cacheKey);
{
String description = buildCampusLogDescription(entity,isNew,oldEntity);
LogContextHolder.setDescription(description);
}
}
/**
* 构建学部操作的详细日志描述
*/
private String buildCampusLogDescription(SchDicCampus newEntity,boolean isNew,SchDicCampus oldEntity) {
if (isNew) {
return String.format("新增校区:%s(序号:%d)",
newEntity.getName(),
newEntity.getSort() != null ? newEntity.getSort() : 0);
} else {
List<String> changes = new ArrayList<>();
if (!Objects.equals(oldEntity.getName(), newEntity.getName())) {
changes.add(String.format("名称从 '%s' 修改为 '%s'", oldEntity.getName(), newEntity.getName()));
}
if (!Objects.equals(oldEntity.getSort(), newEntity.getSort())) {
changes.add(String.format("序号从 %d 修改为 %d", oldEntity.getSort(), newEntity.getSort()));
}
if (changes.isEmpty()) {
return "更新校区:无实际变更";
}
return "更新校区:" + String.join(";", changes);
}
}
@OperationLog(module = LogModule.CAMPUS)
@Transactional(rollbackFor = Exception.class)
public void sortSchCampus(UserContext.UserInfo user,List<Integer> ids)
{
List<SchDicCampus> campusList = getSchDicCampusCacheList(user.getSchId());
Map<Integer, SchDicCampus> campusMap = campusList.stream()
.collect(Collectors.toMap(SchDicCampus::getId, Function.identity()));
Date now = new Date();
// 1. 按传入顺序更新 sort 值
int sortOrder = 1;
for (Integer id : ids) {
SchDicCampus campus = campusMap.get(id);
if (campus != null) {
campus.setSort(sortOrder++);
campus.setUpdateDate(now);
campus.setUpdateUserId(user.getUserId());
}
}
// 2. 处理未出现在排序列表中的校区(设置 sort = null 或一个大值)
for (SchDicCampus campus : campusList) {
if (!ids.contains(campus.getId())) {
campus.setSort(null); // 或者设置一个最大值,比如 999
campus.setUpdateDate(now);
campus.setUpdateUserId(user.getUserId());
}
}
// 批量保存
schDicCampusRepository.saveAll(campusList);
String cacheKey = RedisConstants.SCHOOL_CAMPUS + "_" + user.getSchId();
redisUtil.del(cacheKey);
{
String names = ids.stream()
.map(id -> {
SchDicCampus m = campusMap.get(id);
return m != null ? m.getName() : String.valueOf(id);
})
.collect(Collectors.joining("、"));
String description = String.format("调整校区排序:共 %d 个专业(列表:%s)", ids.size(), names);
LogContextHolder.setDescription(description);
}
}
/**
* 删除校区
* 1. 参数非空校验
* 2. 校验校区是否存在(匹配学校+校区ID,防止跨学校删除)
* 3. 校验校区是否绑定班级,存在关联则禁止删除
* 4. 删除数据库数据 + 清除对应学校校区缓存
* @param id 校区ID
*/
@OperationLog(module = LogModule.CAMPUS)
@Transactional(rollbackFor = Exception.class)
public void delete(UserContext.UserInfo user, Integer id) {
// 1. 参数合法性校验
if (user.getSchId() == null || id == null) {
throw new DException("学校ID、校区ID不能为空");
}
// 2. 校验当前学校下该校区是否存在,防止越权删除其他学校校区
SchDicCampus campus = schDicCampusRepository.findByIdAndSchId(id, user.getSchId())
.orElseThrow(() -> new DException("校区不存在,无法删除"));
// 3. 业务校验:判断校区是否关联班级,有班级则禁止删除
long bindClassCount = schClassRepository.countByCampusId(id);
if (bindClassCount > 0) {
throw new DException(String.format("该校区下存在%s个班级,不可删除,请先移除班级关联", bindClassCount));
}
// 4. 删除数据
schDicCampusRepository.delete(campus);
// 5. 清除当前学校校区缓存
String cacheKey = RedisConstants.SCHOOL_CAMPUS + "_" + user.getSchId();
redisUtil.del(cacheKey);
LogContextHolder.setDescription("删除校区:"+campus.getName());
log.debug("操作人:{},删除校区日志:{}", user.getUserName(), JSON.toJSONString(campus));
}
public List<SelectIntVO> select(Integer schId) {
List<SchDicCampus> list = getSchDicCampusCacheList(schId);
return ModelMapperUtil.toSelectIntVOList(list, SchDicCampus::getId, SchDicCampus::getName);
}
public Map<Integer, String> toIdAndNameMap(Integer schId) {
List<SchDicCampus> list = getSchDicCampusCacheList(schId);
return ModelMapperUtil.toMap(list, SchDicCampus::getId, SchDicCampus::getName);
}
}