1、新增教学大纲,报专业名称重复,其实是code重复,修复;

2、已经限制教员排课的,教员仍然可以排课的问题修复
This commit is contained in:
2026-09-24 11:13:23 +08:00
parent 4f5e219a6e
commit 094245231c
6 changed files with 66 additions and 16 deletions
@@ -108,7 +108,8 @@ public class TrainingProgramController {
@RequestParam(required = false) String zymc, @RequestParam(required = false) String zymc,
@RequestParam(required = false) String zydm, @RequestParam(required = false) String zydm,
@RequestParam(required = false) String pxlx, @RequestParam(required = false) String pxlx,
@RequestParam(required = false) String pxcc) { @RequestParam(required = false) String pxcc,
@RequestParam(required = false) Boolean ty) {
PageQuery query = new PageQuery(); PageQuery query = new PageQuery();
query.setPageNum(pageNum); query.setPageNum(pageNum);
query.setPageSize(pageSize); query.setPageSize(pageSize);
@@ -117,6 +118,7 @@ public class TrainingProgramController {
cond.setZydm(zydm); cond.setZydm(zydm);
cond.setPxlx(pxlx); cond.setPxlx(pxlx);
cond.setPxcc(pxcc); cond.setPxcc(pxcc);
cond.setTy(ty);
PageResult<ZYB> pageResult = trainingProgramService.pageList(query, cond); PageResult<ZYB> pageResult = trainingProgramService.pageList(query, cond);
return Result.success(pageResult); return Result.success(pageResult);
} }
@@ -80,13 +80,7 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
if (xydndxqjbxxb.getZyjsbh() == null || xydndxqjbxxb.getZyjsbh().isEmpty()) { if (xydndxqjbxxb.getZyjsbh() == null || xydndxqjbxxb.getZyjsbh().isEmpty()) {
xydndxqjbxxb.setZyjsbh(init.getZyjsbh()); xydndxqjbxxb.setZyjsbh(init.getZyjsbh());
} }
XYDNDXQJBXXB existing = classSemesterMapper.selectByBcAndNdAndXqdc( assertNoDuplicateSemester(xydndxqjbxxb.getXydbh(), xydndxqjbxxb.getNd(), xydndxqjbxxb.getXqdc(), null);
xydndxqjbxxb.getXydbh(),
String.valueOf(xydndxqjbxxb.getNd()),
String.valueOf(xydndxqjbxxb.getXqdc()));
if (existing != null) {
throw new ServiceException("该班次本年度学期已存在,不能重复新建", CONFLICT);
}
if (xydndxqjbxxb.getYsbbh() == null) { if (xydndxqjbxxb.getYsbbh() == null) {
xydndxqjbxxb.setYsbbh(0); xydndxqjbxxb.setYsbbh(0);
} }
@@ -134,6 +128,10 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
@Override @Override
public void update(XYDNDXQJBXXB xydndxqjbxxb) { public void update(XYDNDXQJBXXB xydndxqjbxxb) {
if (xydndxqjbxxb != null && xydndxqjbxxb.getBh() != null) {
assertNoDuplicateSemester(xydndxqjbxxb.getXydbh(), xydndxqjbxxb.getNd(),
xydndxqjbxxb.getXqdc(), xydndxqjbxxb.getBh());
}
if (xydndxqjbxxb != null && xydndxqjbxxb.getXydbh() != null && xydndxqjbxxb.getXqdc() != null) { if (xydndxqjbxxb != null && xydndxqjbxxb.getXydbh() != null && xydndxqjbxxb.getXqdc() != null) {
com.roomroot.jwgl.vo.elective.SemesterInitVO init = electiveService.getSemesterInit( com.roomroot.jwgl.vo.elective.SemesterInitVO init = electiveService.getSemesterInit(
xydndxqjbxxb.getXydbh(), null, null, xydndxqjbxxb.getXqdc()); xydndxqjbxxb.getXydbh(), null, null, xydndxqjbxxb.getXqdc());
@@ -212,6 +210,7 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
for (String bh : bhList) { for (String bh : bhList) {
XYDNDXQJBXXB xydndxqjbxxb = classSemesterMapper.selectById(bh); XYDNDXQJBXXB xydndxqjbxxb = classSemesterMapper.selectById(bh);
if (xydndxqjbxxb != null) { if (xydndxqjbxxb != null) {
assertNoDuplicateSemester(xydndxqjbxxb.getXydbh(), xydndxqjbxxb.getNd(), xqdc, bh);
xydndxqjbxxb.setXqdc(xqdc); xydndxqjbxxb.setXqdc(xqdc);
classSemesterMapper.updateById(xydndxqjbxxb); classSemesterMapper.updateById(xydndxqjbxxb);
count++; count++;
@@ -220,6 +219,23 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
return count; return count;
} }
/** 同班次不允许存在同学期代号的多行(兼容年度存 4 位年份/6 位学期代号两种口径) */
private void assertNoDuplicateSemester(String xydbh, Integer nd, Integer xqdc, String excludeBh) {
Integer code = SemesterCodeUtil.resolve(nd, xqdc);
if (xydbh == null || code == null) {
return;
}
List<XYDNDXQJBXXB> siblings = classSemesterMapper.selectList(new LambdaQueryWrapper<XYDNDXQJBXXB>()
.eq(XYDNDXQJBXXB::getXydbh, xydbh)
.eq(XYDNDXQJBXXB::getDelFlag, 0));
for (XYDNDXQJBXXB s : siblings) {
if (excludeBh != null && excludeBh.equals(s.getBh())) continue;
if (code.equals(SemesterCodeUtil.resolve(s.getNd(), s.getXqdc()))) {
throw new ServiceException("该班次已存在同学期记录(学期代号 " + code + "),不能重复", CONFLICT);
}
}
}
@Override @Override
public int batchUpdateJxrwbh(List<String> bhList, String jxrwbh) { public int batchUpdateJxrwbh(List<String> bhList, String jxrwbh) {
if (CollectionUtils.isEmpty(bhList)) { if (CollectionUtils.isEmpty(bhList)) {
@@ -1221,6 +1221,8 @@ public class SchedulingWindowServiceImpl implements SchedulingWindowService {
Integer ndCode; Integer ndCode;
List<SSKCXYD> links; List<SSKCXYD> links;
List<SSKCB> lessons; List<SSKCB> lessons;
/** 该学员队所有未开放教员排课的学期代号(同代号多行任一行未开放即视为关闭) */
Set<Integer> closedSemCodes = new HashSet<>();
} }
private Ctx loadCtx(String xydxqbh) { private Ctx loadCtx(String xydxqbh) {
@@ -1235,6 +1237,9 @@ public class SchedulingWindowServiceImpl implements SchedulingWindowService {
ctx.semester = semester; ctx.semester = semester;
ctx.team = xydbMapper.selectById(semester.getXydbh()); ctx.team = xydbMapper.selectById(semester.getXydbh());
ctx.ndCode = SemesterCodeUtil.resolve(semester.getNd(), semester.getXqdc()); ctx.ndCode = SemesterCodeUtil.resolve(semester.getNd(), semester.getXqdc());
markClosedSemesterCodes(ctx, classSemesterMapper.selectList(new LambdaQueryWrapper<XYDNDXQJBXXB>()
.eq(XYDNDXQJBXXB::getXydbh, semester.getXydbh())
.eq(XYDNDXQJBXXB::getDelFlag, 0)));
ctx.links = sskcxydMapper.selectList(new LambdaQueryWrapper<SSKCXYD>() ctx.links = sskcxydMapper.selectList(new LambdaQueryWrapper<SSKCXYD>()
.eq(SSKCXYD::getXydbh, semester.getXydbh()) .eq(SSKCXYD::getXydbh, semester.getXydbh())
.eq(SSKCXYD::getNd, ctx.ndCode)); .eq(SSKCXYD::getNd, ctx.ndCode));
@@ -1279,9 +1284,24 @@ public class SchedulingWindowServiceImpl implements SchedulingWindowService {
ctx.semester = match; ctx.semester = match;
ctx.team = xydbMapper.selectById(xydbh); ctx.team = xydbMapper.selectById(xydbh);
ctx.ndCode = ndCode; ctx.ndCode = ndCode;
markClosedSemesterCodes(ctx, semesters);
return ctx; return ctx;
} }
/** 收集未开放教员排课的学期代号:kfjypk 非 1(含 null)一律按未开放计 */
private void markClosedSemesterCodes(Ctx ctx, List<XYDNDXQJBXXB> teamSemesters) {
for (XYDNDXQJBXXB s : teamSemesters) {
if (s.getKfjypk() != null && s.getKfjypk() == 1) continue;
Integer code = SemesterCodeUtil.resolve(s.getNd(), s.getXqdc());
if (code != null) ctx.closedSemCodes.add(code);
}
}
/** 教员排课是否开放:同学期代号下存在未开放行即关闭;学期缺失按关闭处理 */
private boolean teacherSchedulingOpen(Ctx ctx) {
return ctx.semester != null && ctx.ndCode != null && !ctx.closedSemCodes.contains(ctx.ndCode);
}
private SSKC requireCourse(String sskcbh) { private SSKC requireCourse(String sskcbh) {
if (sskcbh == null || sskcbh.isEmpty()) { if (sskcbh == null || sskcbh.isEmpty()) {
throw new ServiceException("请指定运行课程", BAD_REQUEST); throw new ServiceException("请指定运行课程", BAD_REQUEST);
@@ -1306,7 +1326,7 @@ public class SchedulingWindowServiceImpl implements SchedulingWindowService {
return course.getJybh() != null && jyInOffice(course.getJybh(), officeId); return course.getJybh() != null && jyInOffice(course.getJybh(), officeId);
} }
if (roleHelper.isTeacher()) { if (roleHelper.isTeacher()) {
if (ctx.semester != null && ctx.semester.getKfjypk() != null && ctx.semester.getKfjypk() == 0) { if (!teacherSchedulingOpen(ctx)) {
return false; // 开放教员排课关闭,教员只读 return false; // 开放教员排课关闭,教员只读
} }
String teacherId = roleHelper.findTeacherId(); String teacherId = roleHelper.findTeacherId();
@@ -45,10 +45,24 @@ public class TrainingProgramServiceImpl implements TrainingProgramService {
entity.setTy(false); entity.setTy(false);
entity.setQysj(LocalDateTime.now()); entity.setQysj(LocalDateTime.now());
com.roomroot.jwgl.handler.ZybInsertFillHandler.fillNotNullColumns(entity); com.roomroot.jwgl.handler.ZybInsertFillHandler.fillNotNullColumns(entity);
if (findExistingMajor(entity) != null) { checkDuplicateForAdd(entity);
zybMapper.insert(entity);
}
/**
* 新增前的重复校验:代号撞主键与名称重复分开提示;
* 名称重复只在启用中的记录里判定(已停用记录不占用名称)。
*/
private void checkDuplicateForAdd(ZYB entity) {
if (zybMapper.selectById(entity.getZydh()) != null) {
throw new RuntimeException("专业代号已存在:" + entity.getZydh());
}
java.util.List<ZYB> sameName = zybMapper.selectList(new LambdaQueryWrapper<ZYB>()
.eq(ZYB::getZymc, entity.getZymc())
.eq(ZYB::getTy, false));
if (sameName != null && !sameName.isEmpty()) {
throw new RuntimeException("专业名称已存在,请勿重复新增"); throw new RuntimeException("专业名称已存在,请勿重复新增");
} }
zybMapper.insert(entity);
} }
@Override @Override
@@ -77,10 +91,6 @@ public class TrainingProgramServiceImpl implements TrainingProgramService {
@Override @Override
public PageResult<ZYB> pageList(PageQuery query, ZYB cond) { public PageResult<ZYB> pageList(PageQuery query, ZYB cond) {
// 未显式指定停用条件时,默认只展示启用中的培养方案(停用的不展示)
if (cond != null && cond.getTy() == null) {
cond.setTy(false);
}
Page<ZYB> page = new Page<>(query.getPageNum(), query.getPageSize()); Page<ZYB> page = new Page<>(query.getPageNum(), query.getPageSize());
Page<ZYB> result = zybMapper.selectPageList(page, cond); Page<ZYB> result = zybMapper.selectPageList(page, cond);
return new PageResult<>(result.getRecords(), result.getTotal(), return new PageResult<>(result.getRecords(), result.getTotal(),
@@ -877,6 +877,7 @@ export default {
const ext = [] const ext = []
if (s.nd) ext.push(s.nd + '年') if (s.nd) ext.push(s.nd + '年')
if (s.xqdc) ext.push('第' + s.xqdc + '学期') if (s.xqdc) ext.push('第' + s.xqdc + '学期')
if (Number(s.kfjypk) !== 1) ext.push('未开放教员排课')
return ext.length ? `${name}${ext.join(' ')}` : name return ext.length ? `${name}${ext.join(' ')}` : name
}, },
remainHours(c) { remainHours(c) {
@@ -513,7 +513,8 @@ export default {
this.loading = true this.loading = true
const params = { const params = {
pageNum: this.pageNum, pageNum: this.pageNum,
pageSize: this.pageSize pageSize: this.pageSize,
ty: false
} }
Object.keys(this.searchForm).forEach(key => { Object.keys(this.searchForm).forEach(key => {
const value = this.searchForm[key] const value = this.searchForm[key]