新增教员页面,下拉框乱码修复,保存报错修复

This commit is contained in:
2026-09-15 15:54:06 +08:00
parent 3905e5cb54
commit 9312327112
2 changed files with 192 additions and 12 deletions
@@ -1,5 +1,6 @@
package com.roomroot.jwgl.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.roomroot.jwgl.dto.faculty.AddTeacherDTO;
import com.roomroot.jwgl.entity.*;
@@ -127,20 +128,133 @@ public class FacultyServiceImpl implements FacultyService {
// ==================== 教员管理 ====================
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public void addJYB(AddTeacherDTO dto) {
if (dto == null || dto.getTeacher() == null) {
throw new BusinessException("教员信息不能为空");
}
JYB entity = dto.getTeacher();
//离职状态默认为0
entity.setLzzt(0);
// 教员姓名必填
if (isBlank(entity.getJyxm())) {
throw new BusinessException("教员姓名不能为空");
}
entity.setJyxm(entity.getJyxm().trim());
// 教研室必填:教员表 [教研室代号] 为非空外键,缺失时会直接抛数据库非空约束异常
if (isBlank(entity.getJysdh())) {
throw new BusinessException("请选择所属教研室");
}
entity.setJysdh(entity.getJysdh().trim());
if (jysbMapper.selectById(entity.getJysdh()) == null) {
throw new BusinessException("教研室不存在:" + entity.getJysdh());
}
// 教员编号:前端留空时自动生成(沿用库内既有形态 JY+两位序号),手填时校验唯一
if (isBlank(entity.getJybh())) {
String generated = nextJybh();
entity.setJybh(generated);
// 序号未填时与编号流水号保持一致(库内 JY02 对应 序号=2 的既有约定)
if (isBlank(entity.getXh())) {
String digits = generated.replaceAll("\\D", "");
if (!digits.isEmpty()) {
entity.setXh(String.valueOf(Integer.parseInt(digits)));
}
}
} else {
entity.setJybh(entity.getJybh().trim());
if (jybMapper.selectById(entity.getJybh()) != null) {
throw new BusinessException("教员编号已存在:" + entity.getJybh());
}
}
// 非空列兜底:MyBatis-Plus 只写入非 null 字段,字段为 null 时数据库缺省值不会生效
applyTeacherDefaults(entity);
jybMapper.insert(entity);
// 使用前端传入的教员属性数据
// 使用前端传入的教员属性数据([主任][教员编号] 为非空列,需兜底)
JYSX jysx = dto.getAttributes();
if (jysx != null) {
jysx.setJybh(entity.getJybh());
if (jysx.getZr() == null) {
jysx.setZr(0);
}
jysxMapper.insert(jysx);
}
}
/** 生成下一个教员编号:取库内 JY 前缀编号的最大流水号 +1(JY41、JY42…),异常或全不匹配时退化为 UUID */
private String nextJybh() {
try {
List<JYB> rows = jybMapper.selectList(
new LambdaQueryWrapper<JYB>().select(JYB::getJybh).likeRight(JYB::getJybh, "JY"));
int max = 0;
for (JYB r : rows) {
String code = r.getJybh();
if (code == null || code.length() <= 2) {
continue;
}
String digits = code.substring(2);
if (digits.matches("\\d+")) {
max = Math.max(max, Integer.parseInt(digits));
}
}
for (int seq = max + 1; seq <= max + 500; seq++) {
String candidate = String.format("JY%02d", seq);
if (jybMapper.selectById(candidate) == null) {
return candidate;
}
}
} catch (Exception ignored) {
// 查询异常时退化为 UUID,避免新增教员被阻塞
}
return UuidUtil.getUUID();
}
/** 教员表非空列的默认值兜底(与数据库缺省值保持一致) */
private void applyTeacherDefaults(JYB e) {
if (e.getLzzt() == null) {
e.setLzzt(0);
}
if (e.getXslx() == null) {
e.setXslx(0);
}
if (e.getEwyxkbs() == null) {
e.setEwyxkbs(0);
}
if (e.getXb() == null) {
e.setXb(1);
}
if (e.getWxjy() == null) {
e.setWxjy(0);
}
if (e.getWxyy() == null) {
e.setWxyy(0);
}
if (e.getZzljy() == null) {
e.setZzljy(0);
}
if (isBlank(e.getZyjszwdj())) {
e.setZyjszwdj("初级");
}
if (isBlank(e.getJylb())) {
e.setJylb("专业技术军官");
}
if (isBlank(e.getZzlb())) {
e.setZzlb("在职");
}
if (e.getDslb() == null) {
e.setDslb("");
}
if (e.getXy() == null) {
e.setXy("");
}
}
private boolean isBlank(String s) {
return s == null || s.trim().isEmpty();
}
@Override
@Transactional
public void disableJYB(String jybh) {
@@ -172,15 +286,25 @@ public class FacultyServiceImpl implements FacultyService {
if (list.isEmpty()) {
throw new BusinessException("Excel中无有效数据");
}
for (JYB entity : list) {
for (int i = 0; i < list.size(); i++) {
JYB entity = list.get(i);
// Excel 第 1 行为抬头,故数据行号 = 下标 + 2
int rowNo = i + 2;
if (isBlank(entity.getJyxm())) {
throw new BusinessException("" + rowNo + " 行:教员姓名未填写");
}
// 教研室代号为非空外键,缺失会直接抛数据库非空约束异常,这里给出可定位的提示
if (isBlank(entity.getJysdh())) {
throw new BusinessException("" + rowNo + " 行:教研室代号未填写");
}
// 编号为空自动生成
if (entity.getJybh() == null || entity.getJybh().isEmpty()) {
entity.setJybh(UuidUtil.getUUID());
}
// 离职状态默认 0
if (entity.getLzzt() == null) {
entity.setLzzt(0);
if (isBlank(entity.getJybh())) {
entity.setJybh(nextJybh());
} else if (jybMapper.selectById(entity.getJybh().trim()) != null) {
throw new BusinessException("" + rowNo + " 行:教员编号已存在 " + entity.getJybh());
}
// 离职状态等非空列兜底(数据库缺省值在 MyBatis-Plus 下不会生效)
applyTeacherDefaults(entity);
jybMapper.insert(entity);
}
return list.size();
@@ -98,6 +98,32 @@
>
<el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="160px" class="add-form">
<el-divider content-position="left">教员基本信息</el-divider>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="教员工号" prop="teacher.jybh">
<el-input v-model="addForm.teacher.jybh" placeholder="选填,留空由系统自动生成" maxlength="50" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="教研室" prop="teacher.jysdh">
<el-select
v-model="addForm.teacher.jysdh"
filterable
clearable
placeholder="请选择所属教研室"
:loading="officeLoading"
style="width:100%"
>
<el-option
v-for="item in officeOptions"
:key="item.jysdh"
:label="item.jysmc"
:value="item.jysdh"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="教员姓名" prop="teacher.jyxm"><el-input v-model="addForm.teacher.jyxm" placeholder="请输入" /></el-form-item>
@@ -608,6 +634,7 @@ import {
getTeacherAttribute,
updateTeacherAttribute
} from '@/api/teachOffice/teacher'
import { listOffice } from '@/api/teachOffice/office'
import { getDicts } from '@/api/system/dict/data'
export default {
@@ -629,6 +656,8 @@ export default {
addForm: this.createEmptyAddForm(),
addRules: {
'teacher.jyxm': [{ required: true, message: '请输入教员姓名', trigger: 'blur' }],
'teacher.jysdh': [{ required: true, message: '请选择所属教研室', trigger: 'change' }],
'teacher.jybh': [{ max: 50, message: '教员工号不能超过 50 个字符', trigger: 'blur' }],
'teacher.xh': [{ required: true, message: '请输入序号', trigger: 'blur' }],
'teacher.zyjszwdj': [{ required: true, message: '请输入专业技术职务等级', trigger: 'blur' }],
@@ -679,12 +708,16 @@ export default {
zyjszwdjOptions: [],
jylbOptions: [],
zzlbOptions: [],
dslbOptions: []
dslbOptions: [],
// 教研室下拉(新增教员时选择所属教研室)
officeOptions: [],
officeLoading: false
}
},
mounted() {
this.fetchList()
this.loadDicts()
this.loadOfficeOptions()
},
methods: {
/** 统一格式化后端 LocalDateTime(去除 T、截断到秒) */
@@ -726,6 +759,29 @@ export default {
getDicts('teacher_dslb').then(res => { this.dslbOptions = res.data || [] }).catch(() => {})
},
/** 加载教研室下拉:教员表 [教研室代号] 为非空外键,新增时必须选择 */
loadOfficeOptions() {
this.officeLoading = true
listOffice({ pageNum: 1, pageSize: 500 }).then(response => {
const data = response.data || {}
const rows = data.records || []
const seen = {}
const options = []
rows.forEach(row => {
const jysdh = row.jysdh
// 已停用(ty=1)的教研室不再参与新建教员
if (!jysdh || seen[jysdh] || Number(row.ty) === 1) return
seen[jysdh] = true
options.push({ jysdh, jysmc: row.jysmc || jysdh })
})
this.officeOptions = options
}).catch(() => {
this.officeOptions = []
}).finally(() => {
this.officeLoading = false
})
},
cleanPayload(obj) {
const payload = {}
Object.keys(obj).forEach(key => {