最终版提交

This commit is contained in:
xiao12feng8 2025-12-13 23:19:05 +08:00
parent dfb1c4a7b7
commit 2a816e4abf
11 changed files with 149 additions and 52 deletions

View File

@ -63,6 +63,7 @@ public class StudyClassUserController extends BaseController
/** /**
* 根据班级ID查询用户列表包括老师和学生 * 根据班级ID查询用户列表包括老师和学生
* 使用前端传入的分页参数
*/ */
@PreAuthorize("@ss.hasPermi('study:classUser:list')") @PreAuthorize("@ss.hasPermi('study:classUser:list')")
@GetMapping("/list/{classId}") @GetMapping("/list/{classId}")
@ -372,6 +373,12 @@ public class StudyClassUserController extends BaseController
} }
remark.append("班级名称:").append(importData.getClassName()); remark.append("班级名称:").append(importData.getClassName());
user.setRemark(remark.toString()); user.setRemark(remark.toString());
logger.info("导入数据 - 信息编号={}, 班级名称=[{}], remark=[{}]",
importData.getUserId(), importData.getClassName(), user.getRemark());
}
else
{
logger.info("导入数据 - 信息编号={}, 班级名称为空", importData.getUserId());
} }
String studentStatus = convertStudentStatus(importData.getStudentStatus()); String studentStatus = convertStudentStatus(importData.getStudentStatus());
if (StringUtils.isNotEmpty(studentStatus)) if (StringUtils.isNotEmpty(studentStatus))
@ -485,16 +492,25 @@ public class StudyClassUserController extends BaseController
return null; return null;
} }
String value = studentStatus.trim(); String value = studentStatus.trim();
// 中文转英文
if ("在押".equals(value)) if ("在押".equals(value))
{ {
return "incarcerated"; return "incarcerated";
} }
if ("已释放".equals(value)) if ("已释放".equals(value) || "释放".equals(value))
{ {
return "released"; return "released";
} }
if ("外出".equals(value))
{
return "out";
}
if ("假释".equals(value))
{
return "parole";
}
// 如果已经是英文值直接返回 // 如果已经是英文值直接返回
if ("incarcerated".equals(value) || "released".equals(value)) if ("incarcerated".equals(value) || "released".equals(value) || "out".equals(value) || "parole".equals(value))
{ {
return value; return value;
} }

View File

@ -63,8 +63,8 @@ public class StudentImportData
@Excel(name = "入监时间", sort = 13, width = 30, dateFormat = "yyyy-MM-dd", prompt = "日期格式2024-01-01") @Excel(name = "入监时间", sort = 13, width = 30, dateFormat = "yyyy-MM-dd", prompt = "日期格式2024-01-01")
private Date entryDate; private Date entryDate;
/** 状态(在押/已释放 */ /** 状态(在押/已释放/外出/假释 */
@Excel(name = "状态", sort = 14, readConverterExp = "在押=在押,已释放=已释放", prompt = "填写:在押 或 已释放") @Excel(name = "状态", sort = 14, readConverterExp = "在押=在押,已释放=已释放,释放=释放,外出=外出,假释=假释", prompt = "填写:在押、已释放、外出、假释")
private String studentStatus; private String studentStatus;
public String getClassName() public String getClassName()

View File

@ -869,11 +869,13 @@ public class StudyClassUserServiceImpl implements IStudyClassUserService
{ {
if (StringUtils.isNotEmpty(cls.getClassName())) if (StringUtils.isNotEmpty(cls.getClassName()))
{ {
// 同时存储原始名称和trim后的名称增加匹配成功率
classNameToIdMap.put(cls.getClassName(), cls.getId()); classNameToIdMap.put(cls.getClassName(), cls.getId());
classNameToIdMap.put(cls.getClassName().trim(), cls.getId());
} }
} }
} }
logger.info("预加载班级映射完成,共 {} 个班级", classNameToIdMap.size()); logger.info("预加载班级映射完成,共 {} 个班级,映射内容: {}", allClasses != null ? allClasses.size() : 0, classNameToIdMap);
} }
catch (Exception e) catch (Exception e)
{ {
@ -1022,51 +1024,96 @@ public class StudyClassUserServiceImpl implements IStudyClassUserService
} }
// 尝试分配班级使用缓存的班级映射直接插入关联记录 // 尝试分配班级使用缓存的班级映射直接插入关联记录
// 使用原始的信息编号作为userId因为insertUser后userId可能被自增覆盖
Long studentIdForClass = infoNo;
if (StringUtils.isNotEmpty(user.getRemark())) if (StringUtils.isNotEmpty(user.getRemark()))
{ {
try try
{ {
String remark = user.getRemark(); String remark = user.getRemark();
logger.info("新增用户班级分配 - 用户ID={}, remark={}", studentIdForClass, remark);
int idx = remark.indexOf("班级名称:"); int idx = remark.indexOf("班级名称:");
if (idx >= 0) if (idx >= 0)
{ {
String className = remark.substring(idx + 5).trim(); String className = remark.substring(idx + 5).trim();
logger.info("新增用户班级分配 - 提取的班级名称=[{}], 长度={}", className, className.length());
if (StringUtils.isNotEmpty(className)) if (StringUtils.isNotEmpty(className))
{ {
// 尝试多种匹配方式
Long classId = classNameToIdMap.get(className); Long classId = classNameToIdMap.get(className);
if (classId == null)
{
// 尝试去除所有空白字符后匹配
String classNameNoSpace = className.replaceAll("\\s+", "");
classId = classNameToIdMap.get(classNameNoSpace);
logger.info("新增用户班级分配 - 去空格后尝试匹配: [{}]", classNameNoSpace);
}
logger.info("新增用户班级分配 - 班级名称=[{}], 查找到的classId={}", className, classId);
if (classId != null) if (classId != null)
{ {
// 先禁用所有活跃班级确保一致性虽然新用户不应该有 // 先禁用所有活跃班级
studentClassMapper.deactivateAllActiveClassesByStudentId(user.getUserId()); studentClassMapper.deactivateAllActiveClassesByStudentId(studentIdForClass);
// 插入学员-班级关联 // 检查是否已存在该班级关联可能是之前的记录
StudyStudentClass studentClass = new StudyStudentClass(); StudyStudentClass query = new StudyStudentClass();
studentClass.setStudentId(user.getUserId()); query.setStudentId(studentIdForClass);
studentClass.setClassId(classId); query.setClassId(classId);
studentClass.setStatus(1); // 在读状态 List<StudyStudentClass> existingList = studentClassMapper.selectStudentClassList(query);
studentClass.setJoinTime(new Date());
studentClassMapper.insertStudentClass(studentClass); if (existingList != null && !existingList.isEmpty())
logger.info("为学员 {} 分配班级 {} 成功", infoNo, className); {
// 已存在更新状态为活跃
StudyStudentClass existing = existingList.get(0);
existing.setStatus(1);
existing.setJoinTime(new Date());
studentClassMapper.updateStudentClass(existing);
logger.info("为学员 {} 激活已有班级 {} (classId={}) 成功", infoNo, className, classId);
} }
else else
{ {
// 班级不存在抛出异常 // 不存在插入新记录
throw new ServiceException("班级 [" + className + "] 不存在,请先创建该班级"); StudyStudentClass studentClass = new StudyStudentClass();
studentClass.setStudentId(studentIdForClass);
studentClass.setClassId(classId);
studentClass.setStatus(1);
studentClass.setJoinTime(new Date());
studentClassMapper.insertStudentClass(studentClass);
logger.info("为学员 {} 分配班级 {} (classId={}) 成功", infoNo, className, classId);
} }
} }
else
{
// 班级不存在记录警告但不中断
logger.warn("班级 [{}] 不存在于映射中,可用班级: {}", className, classNameToIdMap.keySet());
}
}
}
else
{
logger.info("新增用户班级分配 - remark中未找到'班级名称:'");
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.warn("为学员 {} 分配班级时失败: {}", infoNo, ex.getMessage()); logger.error("为学员 {} 分配班级时失败: {}", infoNo, ex.getMessage(), ex);
} }
} }
else
{
logger.info("新增用户班级分配 - remark为空跳过班级分配");
}
} }
else else
{ {
// 用户已存在可能是正常用户或已删除用户 // 用户已存在可能是正常用户或已删除用户
boolean isDeleted = "2".equals(u.getDelFlag()); boolean isDeleted = "2".equals(u.getDelFlag());
// 如果不支持更新且用户未被删除报错提示已存在
if (!isUpdateSupport && !isDeleted)
{
throw new ServiceException("信息编号[" + infoNoStr + "]已存在,如需更新请勾选\"更新已存在数据\"");
}
// 强制覆盖所有字段 // 强制覆盖所有字段
u.setNickName(prisonerName); u.setNickName(prisonerName);
u.setPrisonArea(user.getPrisonArea()); u.setPrisonArea(user.getPrisonArea());

View File

@ -161,6 +161,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND u.register_type = 'student' AND u.register_type = 'student'
AND u.prison_area = #{prisonArea} AND u.prison_area = #{prisonArea}
AND sc.class_id = #{classId} AND sc.class_id = #{classId}
AND sc.status = 1
</select> </select>
<!-- 根据用户ID列表批量查询用户不包含数据权限过滤 --> <!-- 根据用户ID列表批量查询用户不包含数据权限过滤 -->
@ -297,8 +298,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="studentStatus != null and studentStatus != ''">student_status,</if> <if test="studentStatus != null and studentStatus != ''">student_status,</if>
create_time create_time
)values( )values(
<if test="userId != null and userId != ''">#{userId},</if> <if test="userId != null and userId != 0">#{userId},</if>
<if test="deptId != null and deptId != ''">#{deptId},</if> <if test="deptId != null and deptId != 0">#{deptId},</if>
<if test="userName != null and userName != ''">#{userName},</if> <if test="userName != null and userName != ''">#{userName},</if>
<choose> <choose>
<when test="nickName != null and nickName != ''">#{nickName}</when> <when test="nickName != null and nickName != ''">#{nickName}</when>

View File

@ -1,10 +1,14 @@
import request from '@/utils/request' import request from '@/utils/request'
// 根据班级ID查询用户列表 // 根据班级ID查询用户列表(后端返回全部数据,前端分页)
export function listClassUsers(classId) { export function listClassUsers(classId) {
return request({ return request({
url: '/study/classUser/list/' + classId, url: '/study/classUser/list/' + classId,
method: 'get' method: 'get',
params: {
pageNum: 1,
pageSize: 99999
}
}) })
} }

View File

@ -886,26 +886,28 @@ export default {
} }
}); });
// //
if (detectedPrisonArea) { const loadClassOptionsPromise = detectedPrisonArea
? getClassesByPrison(detectedPrisonArea).then(res => {
this.filterPrisonArea = detectedPrisonArea; this.filterPrisonArea = detectedPrisonArea;
console.log('[课程分配编辑] 自动设置监区:', detectedPrisonArea);
// onPrisonChange
getClassesByPrison(detectedPrisonArea).then(res => {
this.classOptions = (res.data || []).map(item => ({ this.classOptions = (res.data || []).map(item => ({
...item, ...item,
id: Number(item.id) id: Number(item.id)
})); }));
console.log('[课程分配编辑] 自动设置监区:', detectedPrisonArea);
console.log('[课程分配编辑] 班级选项已加载:', this.classOptions.length); console.log('[课程分配编辑] 班级选项已加载:', this.classOptions.length);
}).catch(() => { }).catch(() => {
this.classOptions = []; this.classOptions = [];
}); })
} : Promise.resolve();
//
loadClassOptionsPromise.then(() => {
// ID // ID
const classStudentMap = new Map(); // Map<classId, { classId, className, students: [] }> const classStudentMap = new Map(); // Map<classId, { classId, className, students: [] }>
console.log('[课程分配编辑] 开始查询学生班级,学生总数:', studentIds.size); console.log('[课程分配编辑] 开始查询学生班级,学生总数:', studentIds.size);
console.log('[课程分配编辑] allStudentOptions数量:', this.allStudentOptions.length); console.log('[课程分配编辑] allStudentOptions数量:', this.allStudentOptions.length);
console.log('[课程分配编辑] classOptions数量:', this.classOptions.length);
const studentPromises = Array.from(studentIds).map(studentId => { const studentPromises = Array.from(studentIds).map(studentId => {
return getClassesByStudentId(studentId).then(classResponse => { return getClassesByStudentId(studentId).then(classResponse => {
const userClassId = classResponse && classResponse.data ? Number(classResponse.data) : null; const userClassId = classResponse && classResponse.data ? Number(classResponse.data) : null;
@ -1001,6 +1003,7 @@ export default {
this.$modal.msgError("处理学生分组失败: " + (error.message || error)); this.$modal.msgError("处理学生分组失败: " + (error.message || error));
this.open = false; this.open = false;
}); });
}); // loadClassOptionsPromise.then
}).catch(error => { }).catch(error => {
console.error('获取课程分配列表失败:', error); console.error('获取课程分配列表失败:', error);
this.$modal.msgError("获取课程分配信息失败: " + (error.message || error)); this.$modal.msgError("获取课程分配信息失败: " + (error.message || error));

View File

@ -40,11 +40,6 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="学员状态" prop="studentStatus"> <el-form-item label="学员状态" prop="studentStatus">
<el-select v-model="queryParams.studentStatus" placeholder="学员状态" clearable style="width: 240px"> <el-select v-model="queryParams.studentStatus" placeholder="学员状态" clearable style="width: 240px">
<el-option v-for="dict in uniqueStudentStatusDicts" :key="dict.value" :label="dict.label" :value="dict.value" /> <el-option v-for="dict in uniqueStudentStatusDicts" :key="dict.value" :label="dict.label" :value="dict.value" />
@ -314,6 +309,16 @@
<el-date-picker v-model="form.entryDate" type="date" placeholder="选择入监时间" value-format="yyyy-MM-dd" style="width: 100%" /> <el-date-picker v-model="form.entryDate" type="date" placeholder="选择入监时间" value-format="yyyy-MM-dd" style="width: 100%" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item label="状态" prop="studentStatus">
<el-select v-model="form.studentStatus" placeholder="请选择状态" style="width: 100%">
<el-option label="在押" value="incarcerated"></el-option>
<el-option label="外出" value="out"></el-option>
<el-option label="假释" value="parole"></el-option>
<el-option label="释放" value="released"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@ -1243,6 +1248,11 @@ export default {
}, },
/** 提交按钮(新增/编辑学员) */ /** 提交按钮(新增/编辑学员) */
submitForm() { submitForm() {
// userId
if (this.form.manualUserId && !this.form.userId) {
this.form.userId = Number(this.form.manualUserId);
}
// userName // userName
// 使 // 使
if (!this.form.userName) { if (!this.form.userName) {
@ -1278,8 +1288,8 @@ export default {
return Promise.resolve(); return Promise.resolve();
}; };
// // 使isEditModeuserId
if (this.form.userId != null && this.form.userId !== undefined) { if (this.isEditMode) {
updateUser(this.form).then(response => { updateUser(this.form).then(response => {
const updated = response.data || this.form; const updated = response.data || this.form;
const userId = updated.userId || this.form.userId; const userId = updated.userId || this.form.userId;
@ -1290,7 +1300,15 @@ export default {
}); });
}); });
} else { } else {
// // -
if (this.form.userId) {
// userId
const existingUser = this.userList.find(u => u.userId == this.form.userId);
if (existingUser) {
this.$modal.msgError(`信息编号 ${this.form.userId} 已存在,请使用其他编号`);
return;
}
}
addUser(this.form).then(response => { addUser(this.form).then(response => {
const created = response.data || {}; const created = response.data || {};
const userId = created.userId; const userId = created.userId;
@ -1342,7 +1360,7 @@ export default {
classAssignMode: 'auto', classAssignMode: 'auto',
classId: undefined, classId: undefined,
originalClassId: undefined, originalClassId: undefined,
studentStatus: undefined studentStatus: 'incarcerated'
}; };
this.isStudentForm = false; this.isStudentForm = false;
this.isEditMode = false; this.isEditMode = false;

View File

@ -410,8 +410,11 @@ export default {
}; };
}, },
created() { created() {
// //
this.getList(); this.getList();
this.getSubjectOptions();
this.getCourseOptions();
this.getClassOptions();
}, },
methods: { methods: {
/** 查询课件列表 */ /** 查询课件列表 */

View File

@ -53,7 +53,6 @@
<el-option label="全部" value="" /> <el-option label="全部" value="" />
<el-option label="单选题" value="single" /> <el-option label="单选题" value="single" />
<el-option label="多选题" value="multiple" /> <el-option label="多选题" value="multiple" />
<el-option label="判断题" value="judge" />
<el-option label="填空题" value="fill" /> <el-option label="填空题" value="fill" />
<el-option label="简答题" value="essay" /> <el-option label="简答题" value="essay" />
</el-select> </el-select>
@ -123,7 +122,6 @@
<el-select v-model="itemForm.questionType" placeholder="请选择题型" style="width: 100%"> <el-select v-model="itemForm.questionType" placeholder="请选择题型" style="width: 100%">
<el-option label="单选题" value="single" /> <el-option label="单选题" value="single" />
<el-option label="多选题" value="multiple" /> <el-option label="多选题" value="multiple" />
<el-option label="判断题" value="judge" />
<el-option label="填空题" value="fill" /> <el-option label="填空题" value="fill" />
<el-option label="简答题" value="essay" /> <el-option label="简答题" value="essay" />
</el-select> </el-select>

View File

@ -1,6 +1,6 @@
-- ============================================ -- ============================================
-- 删除 user_id >= 100 的用户及其关联数据 -- 删除 user_id >= 100 的用户及其关联数据
-- 只删除:用户、学习记录、语音评测、课程分配 -- 只删除:用户、学习记录、语音评测、课程分配、班级关联、角色关联
-- 保留admin(1), ry(2) 等系统用户 -- 保留admin(1), ry(2) 等系统用户
-- 执行前请先备份数据库! -- 执行前请先备份数据库!
-- ============================================ -- ============================================
@ -31,7 +31,14 @@ DELETE FROM voice_evaluation WHERE student_id >= 100;
DELETE FROM course_assignment WHERE student_id >= 100; DELETE FROM course_assignment WHERE student_id >= 100;
-- ============================================ -- ============================================
-- 4. 删除用户 -- 4. 删除班级关联和角色关联
-- ============================================
DELETE FROM student_class WHERE student_id >= 100;
DELETE FROM sys_user_role WHERE user_id >= 100;
-- ============================================
-- 5. 删除用户
-- ============================================ -- ============================================
DELETE FROM sys_user WHERE user_id >= 100; DELETE FROM sys_user WHERE user_id >= 100;

Binary file not shown.