选修课管理
This commit is contained in:
+269
-3
@@ -14,15 +14,19 @@ import com.roomroot.jwgl.entity.JSB;
|
||||
import com.roomroot.jwgl.entity.JYB;
|
||||
import com.roomroot.jwgl.entity.KB;
|
||||
import com.roomroot.jwgl.entity.XYDB;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.entity.XYDQB;
|
||||
import com.roomroot.jwgl.entity.XYDRWB;
|
||||
import com.roomroot.jwgl.entity.ZYB;
|
||||
import com.roomroot.jwgl.mapper.ClassRoomMapper;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.ElectiveCourseMapper;
|
||||
import com.roomroot.jwgl.mapper.JYBMapper;
|
||||
import com.roomroot.jwgl.mapper.KBMapper;
|
||||
import com.roomroot.jwgl.mapper.StudentTeamTaskMapper;
|
||||
import com.roomroot.jwgl.mapper.XYDBMapper;
|
||||
import com.roomroot.jwgl.mapper.XYDQBMapper;
|
||||
import com.roomroot.jwgl.mapper.ZYBMapper;
|
||||
import com.roomroot.jwgl.service.ElectiveCourseService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
@@ -84,6 +88,10 @@ public class ElectiveCourseServiceImpl implements ElectiveCourseService {
|
||||
private ClassRoomMapper classRoomMapper;
|
||||
@Resource
|
||||
private XYDQBMapper xydqbMapper;
|
||||
@Resource
|
||||
private ZYBMapper zybMapper;
|
||||
@Resource
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Override
|
||||
public PageResult<ElectiveCourseVO> pageList(PageQuery query, ElectiveCourseQuery cond) {
|
||||
@@ -103,7 +111,7 @@ public class ElectiveCourseServiceImpl implements ElectiveCourseService {
|
||||
throw new ServiceException("选修课信息不能为空", BAD_REQUEST);
|
||||
}
|
||||
KB course = requireCourse(dto.getKbh());
|
||||
String xydbh = resolveTeamId(dto.getXydbh(), dto.getXxbmc(), dto.getNj(), true);
|
||||
String xydbh = resolveTeamId(dto.getXydbh(), dto.getXxbmc(), dto.getNj(), true, dto.getRs());
|
||||
XYDRWB task = new XYDRWB();
|
||||
task.setBh(UuidUtil.getOriginalUUID());
|
||||
task.setDelFlag(0);
|
||||
@@ -123,6 +131,8 @@ public class ElectiveCourseServiceImpl implements ElectiveCourseService {
|
||||
task.setJysdh(StringUtils.isNotEmpty(dto.getJysdh()) ? dto.getJysdh() : course.getJysdh());
|
||||
task.setBz(dto.getBz());
|
||||
task.setXz(FLAG_DRAFT);
|
||||
task.setXydxqbh(resolveOrCreateSemester(xydbh, task.getNd(), dto.getXqdc(), dto.getKkrq(), dto.getJkrq()));
|
||||
fillTaskRequiredDefaults(task, course);
|
||||
studentTeamTaskMapper.insert(task);
|
||||
upsertPinban(xydbh, STATUS_DRAFT, dto.getBmkssj(), dto.getBmjssj(),
|
||||
dto.getYqsm(), dto.getKxdlbc(), dto.getBz());
|
||||
@@ -245,7 +255,7 @@ public class ElectiveCourseServiceImpl implements ElectiveCourseService {
|
||||
}
|
||||
jsbh = room.getJsbh();
|
||||
}
|
||||
String xydbh = resolveTeamId(null, row.getXxbmc().trim(), row.getKxbcnj(), true);
|
||||
String xydbh = resolveTeamId(null, row.getXxbmc().trim(), row.getKxbcnj(), true, row.getJhrs());
|
||||
XYDRWB task = new XYDRWB();
|
||||
task.setBh(UuidUtil.getOriginalUUID());
|
||||
task.setDelFlag(0);
|
||||
@@ -260,6 +270,9 @@ public class ElectiveCourseServiceImpl implements ElectiveCourseService {
|
||||
task.setKlx(ensureElectiveType(null));
|
||||
task.setJysdh(course.getJysdh());
|
||||
task.setXz(statusToFlag(row.getXkzt()));
|
||||
task.setXydxqbh(resolveOrCreateSemester(xydbh, task.getNd(), null,
|
||||
parseDateTime(row.getKkrq()), parseDateTime(row.getJkrq())));
|
||||
fillTaskRequiredDefaults(task, course);
|
||||
studentTeamTaskMapper.insert(task);
|
||||
upsertPinban(xydbh, normalizeStatus(row.getXkzt()), parseDateTime(row.getBmkssj()),
|
||||
parseDateTime(row.getBmjssj()), row.getYqsm(), row.getKxbcnj(), null);
|
||||
@@ -347,7 +360,7 @@ public class ElectiveCourseServiceImpl implements ElectiveCourseService {
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveTeamId(String xydbh, String xxbmc, String nj, boolean createIfMissing) {
|
||||
private String resolveTeamId(String xydbh, String xxbmc, String nj, boolean createIfMissing, Integer rs) {
|
||||
if (StringUtils.isNotEmpty(xydbh)) {
|
||||
XYDB exists = xydbMapper.selectById(xydbh);
|
||||
if (exists == null) {
|
||||
@@ -371,10 +384,263 @@ public class ElectiveCourseServiceImpl implements ElectiveCourseService {
|
||||
created.setNj(blankToNull(nj));
|
||||
created.setXydlx(CLASS_TYPE_ELECTIVE);
|
||||
created.setXslx(0);
|
||||
created.setXydrs(rs != null ? rs : 0);
|
||||
fillTeamRequiredDefaults(created);
|
||||
xydbMapper.insert(created);
|
||||
return created.getXydbh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 补齐学员队表非空列。优先沿用已有班次上的专业/状态/单位等,避免逐列撞约束。
|
||||
*/
|
||||
private void fillTeamRequiredDefaults(XYDB created) {
|
||||
XYDB template = xydbMapper.selectOne(new LambdaQueryWrapper<XYDB>()
|
||||
.ne(created.getXydbh() != null, XYDB::getXydbh, created.getXydbh())
|
||||
.last("LIMIT 1"));
|
||||
if (template != null) {
|
||||
if (StringUtils.isEmpty(created.getZydh())) {
|
||||
created.setZydh(template.getZydh());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getNj())) {
|
||||
created.setNj(template.getNj());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getZyjsbh())) {
|
||||
created.setZyjsbh(template.getZyjsbh());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getZxzt())) {
|
||||
created.setZxzt(template.getZxzt());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getXh())) {
|
||||
created.setXh(template.getXh());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getRwlb())) {
|
||||
created.setRwlb(template.getRwlb());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getJclb())) {
|
||||
created.setJclb(template.getJclb());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getXtms())) {
|
||||
created.setXtms(template.getXtms());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getJsonzd())) {
|
||||
created.setJsonzd(template.getJsonzd());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getJc())) {
|
||||
created.setJc(template.getJc());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getSsdw())) {
|
||||
created.setSsdw(template.getSsdw());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getPxrwbsh())) {
|
||||
created.setPxrwbsh(template.getPxrwbsh());
|
||||
}
|
||||
if (created.getZtpxrw() == null) {
|
||||
created.setZtpxrw(template.getZtpxrw());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getBz())) {
|
||||
created.setBz(template.getBz());
|
||||
}
|
||||
}
|
||||
if (created.getXydrs() == null) {
|
||||
created.setXydrs(0);
|
||||
}
|
||||
if (created.getXslx() == null) {
|
||||
created.setXslx(0);
|
||||
}
|
||||
if (created.getZtpxrw() == null) {
|
||||
created.setZtpxrw(0);
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getZydh())) {
|
||||
created.setZydh(resolveDefaultZydh());
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getNj())) {
|
||||
created.setNj(String.valueOf(LocalDate.now().getYear()));
|
||||
}
|
||||
if (StringUtils.isEmpty(created.getZxzt())) {
|
||||
created.setZxzt("在校");
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveDefaultZydh() {
|
||||
XYDB existing = xydbMapper.selectOne(new LambdaQueryWrapper<XYDB>()
|
||||
.isNotNull(XYDB::getZydh)
|
||||
.ne(XYDB::getZydh, "")
|
||||
.last("LIMIT 1"));
|
||||
if (existing != null && StringUtils.isNotEmpty(existing.getZydh())) {
|
||||
return existing.getZydh();
|
||||
}
|
||||
ZYB major = zybMapper.selectOne(new LambdaQueryWrapper<ZYB>()
|
||||
.isNotNull(ZYB::getZydh)
|
||||
.ne(ZYB::getZydh, "")
|
||||
.last("LIMIT 1"));
|
||||
if (major != null && StringUtils.isNotEmpty(major.getZydh())) {
|
||||
return major.getZydh();
|
||||
}
|
||||
throw new ServiceException("新建选修班需要专业代号,请先在学科专业中维护专业", BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务表「学员队学期编号」非空且外键到班次学期。按班次+年度+学期第次查找,没有则按班次学期口径新建一条。
|
||||
*/
|
||||
private String resolveOrCreateSemester(String xydbh, Integer taskNd, Integer xqdc,
|
||||
LocalDateTime start, LocalDateTime end) {
|
||||
Integer year = SemesterCodeUtil.toYear(taskNd);
|
||||
if (year == null) {
|
||||
year = LocalDate.now().getYear();
|
||||
}
|
||||
Integer period = xqdc != null ? xqdc : SemesterCodeUtil.toPeriod(taskNd, SemesterCodeUtil.periodOf(LocalDate.now()));
|
||||
if (period == null) {
|
||||
period = 1;
|
||||
}
|
||||
XYDNDXQJBXXB existing = classSemesterMapper.selectByBcAndNdAndXqdc(
|
||||
xydbh, String.valueOf(year), String.valueOf(period));
|
||||
if (existing == null) {
|
||||
existing = classSemesterMapper.selectOne(new LambdaQueryWrapper<XYDNDXQJBXXB>()
|
||||
.eq(XYDNDXQJBXXB::getXydbh, xydbh)
|
||||
.and(w -> w.isNull(XYDNDXQJBXXB::getDelFlag).or().eq(XYDNDXQJBXXB::getDelFlag, 0))
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
if (existing != null) {
|
||||
return existing.getBh();
|
||||
}
|
||||
LocalDate kxrq = start != null ? start.toLocalDate() : LocalDate.now();
|
||||
LocalDate jsrq = end != null ? end.toLocalDate() : kxrq.plusMonths(4);
|
||||
if (!jsrq.isAfter(kxrq)) {
|
||||
jsrq = kxrq.plusMonths(4);
|
||||
}
|
||||
XYDB team = xydbMapper.selectById(xydbh);
|
||||
XYDNDXQJBXXB row = new XYDNDXQJBXXB();
|
||||
row.setBh(UuidUtil.getUUID());
|
||||
row.setXydbh(xydbh);
|
||||
row.setNd(year);
|
||||
row.setXqdc(period);
|
||||
row.setKxrq(kxrq);
|
||||
row.setJsrq(jsrq);
|
||||
row.setXhbs(0);
|
||||
row.setYsbbh(0);
|
||||
row.setKfjypk(0);
|
||||
row.setDelFlag(0);
|
||||
if (team != null) {
|
||||
row.setZyjsbh(team.getZyjsbh());
|
||||
row.setJclb(StringUtils.isNotEmpty(team.getJclb()) ? team.getJclb() : "双节次");
|
||||
row.setXtms(team.getXtms() == null ? "" : team.getXtms());
|
||||
row.setJsonzd(team.getJsonzd());
|
||||
} else {
|
||||
row.setJclb("双节次");
|
||||
row.setXtms("");
|
||||
}
|
||||
classSemesterMapper.insert(row);
|
||||
return row.getBh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 补齐学员队任务表无库默认值的非空列(与教学任务新增同一套口径)。
|
||||
* 计划课次序号、序号标识、编组、配当同班异课选修编组、配档启用自定义学时、学时、课类型、教研室代号。
|
||||
*/
|
||||
private void fillTaskRequiredDefaults(XYDRWB task, KB course) {
|
||||
int seq = nextTaskSequence(task.getXydbh());
|
||||
if (task.getJhkcxh() == null) {
|
||||
task.setJhkcxh(seq);
|
||||
}
|
||||
if (task.getXhbs() == null) {
|
||||
task.setXhbs(task.getJhkcxh());
|
||||
}
|
||||
if (task.getKcxh() == null) {
|
||||
task.setKcxh(task.getJhkcxh());
|
||||
}
|
||||
if (task.getBz2() == null) {
|
||||
task.setBz2(0);
|
||||
}
|
||||
if (task.getPdtbykxxbz() == null) {
|
||||
task.setPdtbykxxbz(1);
|
||||
}
|
||||
if (task.getPdqyzdyxs() == null) {
|
||||
task.setPdqyzdyxs(0);
|
||||
}
|
||||
if (task.getPdxh() == null) {
|
||||
task.setPdxh(0);
|
||||
}
|
||||
if (task.getPdqsz() == null) {
|
||||
task.setPdqsz(0);
|
||||
}
|
||||
if (task.getPdaz() == null) {
|
||||
task.setPdaz(0);
|
||||
}
|
||||
if (task.getPdzzksj() == null) {
|
||||
task.setPdzzksj(0);
|
||||
}
|
||||
if (task.getPdbz() == null) {
|
||||
task.setPdbz(0);
|
||||
}
|
||||
if (task.getXs() == null) {
|
||||
task.setXs(course != null && course.getXs() != null ? course.getXs() : 0);
|
||||
}
|
||||
if (task.getXf() == null) {
|
||||
task.setXf(course != null && course.getXf() != null ? course.getXf() : 0f);
|
||||
}
|
||||
if (task.getRs() == null) {
|
||||
task.setRs(0);
|
||||
}
|
||||
if (task.getXqdc() == null) {
|
||||
task.setXqdc(1);
|
||||
}
|
||||
if (task.getXz() == null) {
|
||||
task.setXz(FLAG_DRAFT);
|
||||
}
|
||||
if (StringUtils.isEmpty(task.getKlx())) {
|
||||
task.setKlx(COURSE_TYPE_ELECTIVE);
|
||||
}
|
||||
if (StringUtils.isEmpty(task.getJysdh())) {
|
||||
String jysdh = course == null ? null : course.getJysdh();
|
||||
task.setJysdh(StringUtils.isNotEmpty(jysdh) ? jysdh : "-");
|
||||
}
|
||||
if (StringUtils.isEmpty(task.getJc()) && course != null) {
|
||||
task.setJc(StringUtils.isNotEmpty(course.getJc()) ? course.getJc() : course.getKmc());
|
||||
}
|
||||
if (task.getKsks() == null) {
|
||||
task.setKsks(course != null && course.getKsks() != null ? course.getKsks() : 0);
|
||||
}
|
||||
if (task.getLlxs() == null) {
|
||||
task.setLlxs(0);
|
||||
}
|
||||
if (task.getSjxs() == null) {
|
||||
task.setSjxs(0);
|
||||
}
|
||||
if (task.getKsksbxs() == null) {
|
||||
task.setKsksbxs(0);
|
||||
}
|
||||
if (task.getBjrxypjf() == null) {
|
||||
task.setBjrxypjf(0);
|
||||
}
|
||||
if (StringUtils.isEmpty(task.getCjfz()) && course != null && StringUtils.isNotEmpty(course.getCjfz())) {
|
||||
task.setCjfz(course.getCjfz());
|
||||
}
|
||||
if (task.getDelFlag() == null) {
|
||||
task.setDelFlag(0);
|
||||
}
|
||||
}
|
||||
|
||||
private int nextTaskSequence(String xydbh) {
|
||||
if (StringUtils.isEmpty(xydbh)) {
|
||||
return 1;
|
||||
}
|
||||
List<XYDRWB> rows = studentTeamTaskMapper.selectList(new LambdaQueryWrapper<XYDRWB>()
|
||||
.eq(XYDRWB::getXydbh, xydbh)
|
||||
.eq(XYDRWB::getDelFlag, 0));
|
||||
int max = 0;
|
||||
if (rows != null) {
|
||||
for (XYDRWB row : rows) {
|
||||
if (row.getJhkcxh() != null && row.getJhkcxh() > max) {
|
||||
max = row.getJhkcxh();
|
||||
}
|
||||
if (row.getXhbs() != null && row.getXhbs() > max) {
|
||||
max = row.getXhbs();
|
||||
}
|
||||
}
|
||||
}
|
||||
return max + 1;
|
||||
}
|
||||
|
||||
private KB requireCourse(String kbh) {
|
||||
if (StringUtils.isEmpty(kbh)) {
|
||||
throw new ServiceException("课程科目不能为空", BAD_REQUEST);
|
||||
|
||||
+12
-2
@@ -170,7 +170,7 @@ public class TaskBookFillServiceImpl implements TaskBookFillService {
|
||||
for (XYDRWB row : rows) {
|
||||
List<String> diff = new ArrayList<>();
|
||||
if (!Objects.equals(row.getKbh(), first.getKbh())) {
|
||||
diff.add("科目(" + row.getKbh() + " ≠ " + first.getKbh() + ")");
|
||||
diff.add("科目(" + subjectLabel(row) + " ≠ " + subjectLabel(first) + ")");
|
||||
}
|
||||
if (!Objects.equals(row.getXs(), first.getXs())) {
|
||||
diff.add("学时(" + row.getXs() + " ≠ " + first.getXs() + ")");
|
||||
@@ -182,12 +182,22 @@ public class TaskBookFillServiceImpl implements TaskBookFillService {
|
||||
diff.add("成绩分制(" + row.getCjfz() + " ≠ " + first.getCjfz() + ")");
|
||||
}
|
||||
if (!diff.isEmpty()) {
|
||||
throw new ServiceException("任务 " + row.getBh() + "(" + row.getXydbh() + ")与第一行不合班:" + String.join("、", diff),
|
||||
throw new ServiceException(
|
||||
"「" + subjectLabel(row) + "」(" + row.getXydbh() + ")与「"
|
||||
+ subjectLabel(first) + "」不合班:" + String.join("、", diff)
|
||||
+ "。合班请选同一科目、不同学员队的行",
|
||||
BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String subjectLabel(XYDRWB row) {
|
||||
if (row.getJc() != null && !row.getJc().isEmpty()) {
|
||||
return row.getJc();
|
||||
}
|
||||
return row.getKbh() == null ? "" : row.getKbh();
|
||||
}
|
||||
|
||||
private static String norm(String s) {
|
||||
return s == null || s.isEmpty() ? "" : s.trim();
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ service.interceptors.response.use(res => {
|
||||
// 未设置状态码则默认成功状态
|
||||
const code = res.data.code || 200
|
||||
// 获取错误信息
|
||||
const msg = errorCode[code] || res.data.msg || errorCode['default']
|
||||
const msg = errorCode[code] || res.data.msg || res.data.message || errorCode['default']
|
||||
// 二进制数据则直接返回
|
||||
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
|
||||
return res.data
|
||||
|
||||
@@ -392,16 +392,41 @@ export default {
|
||||
this.$message.success('操作成功')
|
||||
this.loadRows()
|
||||
})
|
||||
.catch(err => {
|
||||
this.$message.error((err && err.message) || '操作失败')
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
/** 手动合班前置校验:科目/学时/课类型/成绩分制必须相同 */
|
||||
mergeIncompatibleReason(rows) {
|
||||
const first = rows[0]
|
||||
const diffs = []
|
||||
const courses = [...new Set(rows.map(r => r.kcmc || r.kbh || ''))].filter(Boolean)
|
||||
if (rows.some(r => r.kbh !== first.kbh)) {
|
||||
diffs.push('科目不同(' + (courses.join('、') || '课号不一致') + ')')
|
||||
}
|
||||
if (rows.some(r => r.xs !== first.xs)) {
|
||||
diffs.push('学时不同')
|
||||
}
|
||||
if (rows.some(r => r.klx !== first.klx)) {
|
||||
diffs.push('课类型不同')
|
||||
}
|
||||
const norm = v => (v == null || v === '' ? '' : String(v).trim())
|
||||
if (rows.some(r => norm(r.cjfz) !== norm(first.cjfz))) {
|
||||
diffs.push('成绩分制不同')
|
||||
}
|
||||
if (!diffs.length) return ''
|
||||
return '不能手动合班:' + diffs.join(';') + '。请选择同一科目、同一学时、同一课类型、同一成绩分制的行(通常是不同学员队的同一门课)'
|
||||
},
|
||||
handleMerge() {
|
||||
const bhList = this.selection.map(r => r.bh)
|
||||
if (bhList.length < 2) {
|
||||
const selected = this.selection
|
||||
if (selected.length < 2) {
|
||||
this.$message.warning('请至少选择两行进行合班')
|
||||
return
|
||||
}
|
||||
const reason = this.mergeIncompatibleReason(selected)
|
||||
if (reason) {
|
||||
this.$message.warning(reason)
|
||||
return
|
||||
}
|
||||
const bhList = selected.map(r => r.bh)
|
||||
this.$confirm(`把选中的 ${bhList.length} 行合成一个班?`, '手动合班', { type: 'warning' })
|
||||
.then(() => this.reload(taskBookMerge(bhList).then(res => {
|
||||
this.$message.info(`已合入编组 ${res.data}`)
|
||||
|
||||
Reference in New Issue
Block a user