wuzhen 班级管理功能提交

This commit is contained in:
wuzhen committed 2025-07-17 10:29:09 +08:00
1 parent 6820ebc45f
commit c809141195
12 files changed
+4731

No files matched your search

@@ -0,0 +1,265 @@
package org.dromara.xg.controller;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.xg.domain.vo.XgClassInfoVo;
import org.dromara.xg.domain.bo.XgClassInfoBo;
import org.dromara.xg.service.IXgClassInfoService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 班级信息管理
*
* @author Cursor AI
* @date 2025-01-21
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/xg/classInfo")
public class XgClassInfoController extends BaseController {
private final IXgClassInfoService xgClassInfoService;
/**
* 查询班级信息列表
*/
@SaCheckPermission("xg:classInfo:list")
@GetMapping("/list")
public TableDataInfo<XgClassInfoVo> list(XgClassInfoBo bo, PageQuery pageQuery) {
return xgClassInfoService.queryPageList(bo, pageQuery);
}
/**
* 导出班级信息列表
*/
@SaCheckPermission("xg:classInfo:export")
@Log(title = "班级信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(XgClassInfoBo bo, HttpServletResponse response) {
List<XgClassInfoVo> list = xgClassInfoService.queryList(bo);
ExcelUtil.exportExcel(list, "班级信息", XgClassInfoVo.class, response);
}
/**
* 获取班级信息详细信息
*/
@SaCheckPermission("xg:classInfo:query")
@GetMapping("/{id}")
public R<XgClassInfoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(xgClassInfoService.queryById(id));
}
/**
* 新增班级信息
*/
@SaCheckPermission("xg:classInfo:add")
@Log(title = "班级信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody XgClassInfoBo bo) {
return toAjax(xgClassInfoService.insertByBo(bo));
}
/**
* 修改班级信息
*/
@SaCheckPermission("xg:classInfo:edit")
@Log(title = "班级信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XgClassInfoBo bo) {
return toAjax(xgClassInfoService.updateByBo(bo));
}
/**
* 删除班级信息
*/
@SaCheckPermission("xg:classInfo:remove")
@Log(title = "班级信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(xgClassInfoService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 根据班级代码查询班级信息
*/
@SaCheckPermission("xg:classInfo:query")
@GetMapping("/getByClassCode/{classCode}")
public R<XgClassInfoVo> getByClassCode(@NotBlank(message = "班级代码不能为空")
@PathVariable String classCode) {
return R.ok(xgClassInfoService.queryByClassCode(classCode));
}
/**
* 根据年级查询班级信息列表
*/
@SaCheckPermission("xg:classInfo:query")
@GetMapping("/getByGrade/{grade}")
public R<List<XgClassInfoVo>> getByGrade(@NotBlank(message = "年级不能为空")
@PathVariable String grade) {
return R.ok(xgClassInfoService.queryByGrade(grade));
}
/**
* 根据学院代码查询班级信息列表
*/
@SaCheckPermission("xg:classInfo:query")
@GetMapping("/getByCollegeCode/{collegeCode}")
public R<List<XgClassInfoVo>> getByCollegeCode(@NotBlank(message = "学院代码不能为空")
@PathVariable String collegeCode) {
return R.ok(xgClassInfoService.queryByCollegeCode(collegeCode));
}
/**
* 根据专业代码查询班级信息列表
*/
@SaCheckPermission("xg:classInfo:query")
@GetMapping("/getByMajorCode/{majorCode}")
public R<List<XgClassInfoVo>> getByMajorCode(@NotBlank(message = "专业代码不能为空")
@PathVariable String majorCode) {
return R.ok(xgClassInfoService.queryByMajorCode(majorCode));
}
/**
* 根据辅导员ID查询班级信息列表
*/
@SaCheckPermission("xg:classInfo:query")
@GetMapping("/getByCounselorId/{counselorId}")
public R<List<XgClassInfoVo>> getByCounselorId(@NotNull(message = "辅导员ID不能为空")
@PathVariable Long counselorId) {
return R.ok(xgClassInfoService.queryByCounselorId(counselorId));
}
/**
* 根据班主任ID查询班级信息列表
*/
@SaCheckPermission("xg:classInfo:query")
@GetMapping("/getByClassTeacherId/{classTeacherId}")
public R<List<XgClassInfoVo>> getByClassTeacherId(@NotNull(message = "班主任ID不能为空")
@PathVariable Long classTeacherId) {
return R.ok(xgClassInfoService.queryByClassTeacherId(classTeacherId));
}
/**
* 获取班级可用选项列表(用于下拉框)
*/
@SaCheckPermission("xg:classInfo:query")
@GetMapping("/getClassOptions")
public R<List<XgClassInfoVo>> getClassOptions() {
return R.ok(xgClassInfoService.getClassOptions());
}
/**
* 更新班级学生统计数据
*/
@SaCheckPermission("xg:classInfo:edit")
@Log(title = "班级信息", businessType = BusinessType.UPDATE)
@PostMapping("/updateStudentCount/{id}")
public R<Void> updateStudentCount(@NotNull(message = "班级ID不能为空")
@PathVariable Long id) {
return toAjax(xgClassInfoService.updateStudentCount(id));
}
/**
* 批量更新班级学生统计数据
*/
@SaCheckPermission("xg:classInfo:edit")
@Log(title = "班级信息", businessType = BusinessType.UPDATE)
@PostMapping("/batchUpdateStudentCount")
public R<Void> batchUpdateStudentCount(@NotEmpty(message = "班级ID列表不能为空")
@RequestBody List<Long> ids) {
return toAjax(xgClassInfoService.batchUpdateStudentCount(ids));
}
/**
* 启用班级
*/
@SaCheckPermission("xg:classInfo:edit")
@Log(title = "班级信息", businessType = BusinessType.UPDATE)
@PostMapping("/enable/{id}")
public R<Void> enable(@NotNull(message = "班级ID不能为空")
@PathVariable Long id) {
return toAjax(xgClassInfoService.enableClass(id));
}
/**
* 禁用班级
*/
@SaCheckPermission("xg:classInfo:edit")
@Log(title = "班级信息", businessType = BusinessType.UPDATE)
@PostMapping("/disable/{id}")
public R<Void> disable(@NotNull(message = "班级ID不能为空")
@PathVariable Long id) {
return toAjax(xgClassInfoService.disableClass(id));
}
// ================================
// 统计数据接口 - 新增
// ================================
/**
* 获取班级信息统计概览
*/
@SaCheckPermission("xg:classInfo:statistics")
@GetMapping("/statistics")
public R<Map<String, Object>> getStatistics() {
return R.ok(xgClassInfoService.getStatistics());
}
/**
* 统计各学院班级数量
*/
@SaCheckPermission("xg:classInfo:statistics")
@GetMapping("/statistics/college")
public R<List<Map<String, Object>>> countByCollege() {
return R.ok(xgClassInfoService.countByCollege());
}
/**
* 统计各年级班级数量
*/
@SaCheckPermission("xg:classInfo:statistics")
@GetMapping("/statistics/grade")
public R<List<Map<String, Object>>> countByGrade() {
return R.ok(xgClassInfoService.countByGrade());
}
/**
* 统计各专业班级数量
*/
@SaCheckPermission("xg:classInfo:statistics")
@GetMapping("/statistics/major")
public R<List<Map<String, Object>>> countByMajor() {
return R.ok(xgClassInfoService.countByMajor());
}
/**
* 统计班级状态分布
*/
@SaCheckPermission("xg:classInfo:statistics")
@GetMapping("/statistics/status")
public R<List<Map<String, Object>>> countByStatus() {
return R.ok(xgClassInfoService.countByStatus());
}
}
@@ -0,0 +1,346 @@
package org.dromara.xg.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 班级信息对象 xg_class_info
*
* @author Cursor AI
* @date 2025-01-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xg_class_info")
public class XgClassInfo extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 班级ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 租户编号
*/
@TableField("tenant_id")
private String tenantId;
/**
* 班级代码
*/
@TableField("class_code")
private String classCode;
/**
* 班级名称
*/
@TableField("class_name")
private String className;
/**
* 班级类型:regular-普通班级,honor-荣誉班级,experimental-实验班级,special-特殊班级
*/
@TableField("class_type")
private String classType;
/**
* 年级
*/
@TableField("grade")
private String grade;
/**
* 入学年份
*/
@TableField("enrollment_year")
private Integer enrollmentYear;
/**
* 毕业年份
*/
@TableField("graduation_year")
private Integer graduationYear;
/**
* 专业代码
*/
@TableField("major_code")
private String majorCode;
/**
* 专业名称
*/
@TableField("major_name")
private String majorName;
/**
* 培养方式:全日制、在职、函授、夜大等
*/
@TableField("training_type")
private String trainingType;
/**
* 学位类型:本科、专科、研究生等
*/
@TableField("degree_type")
private String degreeType;
/**
* 学院代码
*/
@TableField("college_code")
private String collegeCode;
/**
* 学院名称
*/
@TableField("college_name")
private String collegeName;
/**
* 辅导员ID
*/
@TableField("counselor_id")
private Long counselorId;
/**
* 辅导员姓名
*/
@TableField("counselor_name")
private String counselorName;
/**
* 班主任ID
*/
@TableField("class_teacher_id")
private Long classTeacherId;
/**
* 班主任姓名
*/
@TableField("class_teacher_name")
private String classTeacherName;
/**
* 班级导师ID
*/
@TableField("class_advisor_id")
private Long classAdvisorId;
/**
* 班级导师姓名
*/
@TableField("class_advisor_name")
private String classAdvisorName;
/**
* 班长ID
*/
@TableField("class_monitor_id")
private Long classMonitorId;
/**
* 班长姓名
*/
@TableField("class_monitor_name")
private String classMonitorName;
/**
* 副班长ID
*/
@TableField("deputy_monitor_id")
private Long deputyMonitorId;
/**
* 副班长姓名
*/
@TableField("deputy_monitor_name")
private String deputyMonitorName;
/**
* 班级状态:1-正常,2-暂停,3-毕业,4-解散
*/
@TableField("class_status")
private String classStatus;
/**
* 是否毕业:0-未毕业,1-已毕业
*/
@TableField("is_graduation")
private Integer isGraduation;
/**
* 毕业日期
*/
@TableField("graduation_date")
private LocalDate graduationDate;
/**
* 计划容量
*/
@TableField("planned_capacity")
private Integer plannedCapacity;
/**
* 当前学生数量
*/
@TableField("current_student_count")
private Integer currentStudentCount;
/**
* 最大学生数量
*/
@TableField("max_student_count")
private Integer maxStudentCount;
/**
* 男生数量
*/
@TableField("male_count")
private Integer maleCount;
/**
* 女生数量
*/
@TableField("female_count")
private Integer femaleCount;
/**
* 在籍学生数量
*/
@TableField("active_count")
private Integer activeCount;
/**
* 转入学生数量
*/
@TableField("transfer_in_count")
private Integer transferInCount;
/**
* 转出学生数量
*/
@TableField("transfer_out_count")
private Integer transferOutCount;
/**
* 退学学生数量
*/
@TableField("dropout_count")
private Integer dropoutCount;
/**
* 毕业学生数量
*/
@TableField("graduate_count")
private Integer graduateCount;
/**
* 办公室位置
*/
@TableField("office_location")
private String officeLocation;
/**
* 教室位置
*/
@TableField("class_location")
private String classLocation;
/**
* 联系电话
*/
@TableField("contact_phone")
private String contactPhone;
/**
* QQ群号
*/
@TableField("qq_group")
private String qqGroup;
/**
* 微信群
*/
@TableField("wechat_group")
private String wechatGroup;
/**
* 邮箱
*/
@TableField("email")
private String email;
/**
* 课程安排
*/
@TableField("class_schedule")
private String classSchedule;
/**
* 班级文化
*/
@TableField("class_culture")
private String classCulture;
/**
* 班级规章制度
*/
@TableField("class_rules")
private String classRules;
/**
* 班级描述
*/
@TableField("class_description")
private String classDescription;
/**
* 最后统计更新时间
*/
@TableField("last_count_update")
private LocalDateTime lastCountUpdate;
/**
* 扩展字段1
*/
@TableField("ext_field1")
private String extField1;
/**
* 扩展字段2
*/
@TableField("ext_field2")
private String extField2;
/**
* 扩展字段3
*/
@TableField("ext_field3")
private String extField3;
/**
* 备注
*/
@TableField("remark")
private String remark;
/**
* 删除标志(0代表存在 1代表删除)
*/
@TableField("deleted")
@TableLogic
private Integer deleted;
}
@@ -0,0 +1,378 @@
package org.dromara.xg.domain.bo;
import org.dromara.xg.domain.XgClassInfo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* 班级信息业务对象 xg_class_info
*
* @author Cursor AI
* @date 2025-01-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = XgClassInfo.class, reverseConvertGenerate = false)
public class XgClassInfoBo extends BaseEntity {
/**
* 班级ID
*/
@NotNull(message = "班级ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 班级代码
*/
@NotBlank(message = "班级代码不能为空", groups = { AddGroup.class, EditGroup.class })
@Size(max = 32, message = "班级代码长度不能超过32个字符")
private String classCode;
/**
* 班级名称
*/
@NotBlank(message = "班级名称不能为空", groups = { AddGroup.class, EditGroup.class })
@Size(max = 100, message = "班级名称长度不能超过100个字符")
private String className;
/**
* 班级类型:regular-普通班级,honor-荣誉班级,experimental-实验班级,special-特殊班级
*/
private String classType;
/**
* 年级
*/
@NotBlank(message = "年级不能为空", groups = { AddGroup.class, EditGroup.class })
@Size(max = 10, message = "年级长度不能超过10个字符")
private String grade;
/**
* 入学年份
*/
@NotNull(message = "入学年份不能为空", groups = { AddGroup.class, EditGroup.class })
@Min(value = 1900, message = "入学年份不能小于1900")
@Max(value = 2100, message = "入学年份不能大于2100")
private Integer enrollmentYear;
/**
* 毕业年份
*/
@Min(value = 1900, message = "毕业年份不能小于1900")
@Max(value = 2100, message = "毕业年份不能大于2100")
private Integer graduationYear;
/**
* 专业代码
*/
@Size(max = 20, message = "专业代码长度不能超过20个字符")
private String majorCode;
/**
* 专业名称
*/
@Size(max = 100, message = "专业名称长度不能超过100个字符")
private String majorName;
/**
* 培养方式:全日制、在职、函授、夜大等
*/
@Size(max = 20, message = "培养方式长度不能超过20个字符")
private String trainingType;
/**
* 学位类型:本科、专科、研究生等
*/
@Size(max = 20, message = "学位类型长度不能超过20个字符")
private String degreeType;
/**
* 学院代码
*/
@Size(max = 20, message = "学院代码长度不能超过20个字符")
private String collegeCode;
/**
* 学院名称
*/
@Size(max = 100, message = "学院名称长度不能超过100个字符")
private String collegeName;
/**
* 辅导员ID
*/
private Long counselorId;
/**
* 辅导员姓名
*/
@Size(max = 50, message = "辅导员姓名长度不能超过50个字符")
private String counselorName;
/**
* 班主任ID
*/
private Long classTeacherId;
/**
* 班主任姓名
*/
@Size(max = 50, message = "班主任姓名长度不能超过50个字符")
private String classTeacherName;
/**
* 班级导师ID
*/
private Long classAdvisorId;
/**
* 班级导师姓名
*/
@Size(max = 50, message = "班级导师姓名长度不能超过50个字符")
private String classAdvisorName;
/**
* 班长ID
*/
private Long classMonitorId;
/**
* 班长姓名
*/
@Size(max = 50, message = "班长姓名长度不能超过50个字符")
private String classMonitorName;
/**
* 副班长ID
*/
private Long deputyMonitorId;
/**
* 副班长姓名
*/
@Size(max = 50, message = "副班长姓名长度不能超过50个字符")
private String deputyMonitorName;
/**
* 班级状态:1-正常,2-暂停,3-毕业,4-解散
*/
private String classStatus;
/**
* 是否毕业:0-未毕业,1-已毕业
*/
private Integer isGraduation;
/**
* 毕业日期
*/
private LocalDate graduationDate;
/**
* 计划容量
*/
@Min(value = 1, message = "计划容量不能小于1")
@Max(value = 200, message = "计划容量不能大于200")
private Integer plannedCapacity;
/**
* 当前学生数量
*/
private Integer currentStudentCount;
/**
* 最大学生数量
*/
@Min(value = 1, message = "最大学生数量不能小于1")
@Max(value = 200, message = "最大学生数量不能大于200")
private Integer maxStudentCount;
/**
* 男生数量
*/
private Integer maleCount;
/**
* 女生数量
*/
private Integer femaleCount;
/**
* 在籍学生数量
*/
private Integer activeCount;
/**
* 转入学生数量
*/
private Integer transferInCount;
/**
* 转出学生数量
*/
private Integer transferOutCount;
/**
* 退学学生数量
*/
private Integer dropoutCount;
/**
* 毕业学生数量
*/
private Integer graduateCount;
/**
* 办公室位置
*/
@Size(max = 200, message = "办公室位置长度不能超过200个字符")
private String officeLocation;
/**
* 教室位置
*/
@Size(max = 100, message = "教室位置长度不能超过100个字符")
private String classLocation;
/**
* 联系电话
*/
@Size(max = 20, message = "联系电话长度不能超过20个字符")
private String contactPhone;
/**
* QQ群号
*/
@Size(max = 20, message = "QQ群号长度不能超过20个字符")
private String qqGroup;
/**
* 微信群
*/
@Size(max = 100, message = "微信群长度不能超过100个字符")
private String wechatGroup;
/**
* 邮箱
*/
@Email(message = "邮箱格式不正确")
@Size(max = 100, message = "邮箱长度不能超过100个字符")
private String email;
/**
* 课程安排
*/
private String classSchedule;
/**
* 班级文化
*/
private String classCulture;
/**
* 班级规章制度
*/
private String classRules;
/**
* 班级描述
*/
@Size(max = 500, message = "班级描述长度不能超过500个字符")
private String classDescription;
/**
* 最后统计更新时间
*/
private LocalDateTime lastCountUpdate;
/**
* 扩展字段1
*/
@Size(max = 200, message = "扩展字段1长度不能超过200个字符")
private String extField1;
/**
* 扩展字段2
*/
@Size(max = 200, message = "扩展字段2长度不能超过200个字符")
private String extField2;
/**
* 扩展字段3
*/
@Size(max = 200, message = "扩展字段3长度不能超过200个字符")
private String extField3;
/**
* 备注
*/
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark;
// ========== 查询条件字段 ==========
/**
* 入学年份开始
*/
private Integer enrollmentYearStart;
/**
* 入学年份结束
*/
private Integer enrollmentYearEnd;
/**
* 班级代码列表(用于批量查询)
*/
private List<String> classCodeList;
/**
* 班级状态列表(用于批量查询)
*/
private List<String> classStatusList;
/**
* 学院代码列表(用于批量查询)
*/
private List<String> collegeCodeList;
/**
* 专业代码列表(用于批量查询)
*/
private List<String> majorCodeList;
/**
* 年级列表(用于批量查询)
*/
private List<String> gradeList;
/**
* 辅导员ID列表(用于批量查询)
*/
private List<Long> counselorIdList;
/**
* 班主任ID列表(用于批量查询)
*/
private List<Long> classTeacherIdList;
/**
* 创建时间开始
*/
private String createTimeStart;
/**
* 创建时间结束
*/
private String createTimeEnd;
}
@@ -0,0 +1,355 @@
package org.dromara.xg.domain.vo;
import org.dromara.xg.domain.XgClassInfo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 班级信息视图对象 xg_class_info
*
* @author Cursor AI
* @date 2025-01-21
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XgClassInfo.class)
public class XgClassInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 班级ID
*/
@ExcelProperty(value = "班级ID")
private Long id;
/**
* 班级代码
*/
@ExcelProperty(value = "班级代码")
private String classCode;
/**
* 班级名称
*/
@ExcelProperty(value = "班级名称")
private String className;
/**
* 班级类型:regular-普通班级,honor-荣誉班级,experimental-实验班级,special-特殊班级
*/
@ExcelProperty(value = "班级类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_class_type")
private String classType;
/**
* 年级
*/
@ExcelProperty(value = "年级")
private String grade;
/**
* 入学年份
*/
@ExcelProperty(value = "入学年份")
private Integer enrollmentYear;
/**
* 毕业年份
*/
@ExcelProperty(value = "毕业年份")
private Integer graduationYear;
/**
* 专业代码
*/
@ExcelProperty(value = "专业代码")
private String majorCode;
/**
* 专业名称
*/
@ExcelProperty(value = "专业名称")
private String majorName;
/**
* 培养方式:全日制、在职、函授、夜大等
*/
@ExcelProperty(value = "培养方式")
private String trainingType;
/**
* 学位类型:本科、专科、研究生等
*/
@ExcelProperty(value = "学位类型")
private String degreeType;
/**
* 学院代码
*/
@ExcelProperty(value = "学院代码")
private String collegeCode;
/**
* 学院名称
*/
@ExcelProperty(value = "学院名称")
private String collegeName;
/**
* 辅导员ID
*/
private Long counselorId;
/**
* 辅导员姓名
*/
@ExcelProperty(value = "辅导员姓名")
private String counselorName;
/**
* 班主任ID
*/
private Long classTeacherId;
/**
* 班主任姓名
*/
@ExcelProperty(value = "班主任姓名")
private String classTeacherName;
/**
* 班级导师ID
*/
private Long classAdvisorId;
/**
* 班级导师姓名
*/
@ExcelProperty(value = "班级导师姓名")
private String classAdvisorName;
/**
* 班长ID
*/
private Long classMonitorId;
/**
* 班长姓名
*/
@ExcelProperty(value = "班长姓名")
private String classMonitorName;
/**
* 副班长ID
*/
private Long deputyMonitorId;
/**
* 副班长姓名
*/
@ExcelProperty(value = "副班长姓名")
private String deputyMonitorName;
/**
* 班级状态:1-正常,2-暂停,3-毕业,4-解散
*/
@ExcelProperty(value = "班级状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "xg_class_status")
private String classStatus;
/**
* 是否毕业:0-未毕业,1-已毕业
*/
@ExcelProperty(value = "是否毕业", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=未毕业,1=已毕业")
private Integer isGraduation;
/**
* 毕业日期
*/
@ExcelProperty(value = "毕业日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate graduationDate;
/**
* 计划容量
*/
@ExcelProperty(value = "计划容量")
private Integer plannedCapacity;
/**
* 当前学生数量
*/
@ExcelProperty(value = "当前学生数量")
private Integer currentStudentCount;
/**
* 最大学生数量
*/
@ExcelProperty(value = "最大学生数量")
private Integer maxStudentCount;
/**
* 男生数量
*/
@ExcelProperty(value = "男生数量")
private Integer maleCount;
/**
* 女生数量
*/
@ExcelProperty(value = "女生数量")
private Integer femaleCount;
/**
* 在籍学生数量
*/
@ExcelProperty(value = "在籍学生数量")
private Integer activeCount;
/**
* 转入学生数量
*/
@ExcelProperty(value = "转入学生数量")
private Integer transferInCount;
/**
* 转出学生数量
*/
@ExcelProperty(value = "转出学生数量")
private Integer transferOutCount;
/**
* 退学学生数量
*/
@ExcelProperty(value = "退学学生数量")
private Integer dropoutCount;
/**
* 毕业学生数量
*/
@ExcelProperty(value = "毕业学生数量")
private Integer graduateCount;
/**
* 办公室位置
*/
@ExcelProperty(value = "办公室位置")
private String officeLocation;
/**
* 教室位置
*/
@ExcelProperty(value = "教室位置")
private String classLocation;
/**
* 联系电话
*/
@ExcelProperty(value = "联系电话")
private String contactPhone;
/**
* QQ群号
*/
@ExcelProperty(value = "QQ群号")
private String qqGroup;
/**
* 微信群
*/
@ExcelProperty(value = "微信群")
private String wechatGroup;
/**
* 邮箱
*/
@ExcelProperty(value = "邮箱")
private String email;
/**
* 课程安排
*/
private String classSchedule;
/**
* 班级文化
*/
private String classCulture;
/**
* 班级规章制度
*/
private String classRules;
/**
* 班级描述
*/
@ExcelProperty(value = "班级描述")
private String classDescription;
/**
* 最后统计更新时间
*/
@ExcelProperty(value = "最后统计更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime lastCountUpdate;
/**
* 扩展字段1
*/
private String extField1;
/**
* 扩展字段2
*/
private String extField2;
/**
* 扩展字段3
*/
private String extField3;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 创建者
*/
private Long createBy;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
/**
* 更新者
*/
private Long updateBy;
/**
* 更新时间
*/
@ExcelProperty(value = "更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
}
@@ -0,0 +1,106 @@
package org.dromara.xg.mapper;
import org.dromara.xg.domain.XgClassInfo;
import org.dromara.xg.domain.vo.XgClassInfoVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 班级信息Mapper接口
*
* @author Cursor AI
* @date 2025-01-21
*/
public interface XgClassInfoMapper extends BaseMapperPlus<XgClassInfo, XgClassInfoVo> {
/**
* 重写分页查询方法,使用自定义ResultMap
*
* @param page 分页参数
* @param wrapper 查询条件
* @return 分页结果
*/
<P extends IPage<XgClassInfoVo>> P selectVoPage(IPage<XgClassInfo> page, @Param("ew") Wrapper<XgClassInfo> wrapper);
/**
* 根据班级代码查询班级信息
*
* @param classCode 班级代码
* @return 班级信息
*/
XgClassInfoVo selectByClassCode(String classCode);
/**
* 查询指定年级的班级列表
*
* @param grade 年级
* @return 班级列表
*/
List<XgClassInfoVo> selectByGrade(String grade);
/**
* 查询指定学院的班级列表
*
* @param collegeCode 学院代码
* @return 班级列表
*/
List<XgClassInfoVo> selectByCollegeCode(String collegeCode);
/**
* 查询指定专业的班级列表
*
* @param majorCode 专业代码
* @return 班级列表
*/
List<XgClassInfoVo> selectByMajorCode(String majorCode);
/**
* 查询指定辅导员的班级列表
*
* @param counselorId 辅导员ID
* @return 班级列表
*/
List<XgClassInfoVo> selectByCounselorId(Long counselorId);
/**
* 查询指定班主任的班级列表
*
* @param classTeacherId 班主任ID
* @return 班级列表
*/
List<XgClassInfoVo> selectByClassTeacherId(Long classTeacherId);
/**
* 统计各学院班级数量
*
* @return 学院班级数量统计
*/
List<Map<String, Object>> countByCollege();
/**
* 统计各年级班级数量
*
* @return 年级班级数量统计
*/
List<Map<String, Object>> countByGrade();
/**
* 统计各专业班级数量
*
* @return 专业班级数量统计
*/
List<Map<String, Object>> countByMajor();
/**
* 统计班级状态分布
*
* @return 班级状态统计
*/
List<Map<String, Object>> countByClassStatus();
}
@@ -0,0 +1,195 @@
package org.dromara.xg.service;
import org.dromara.xg.domain.vo.XgClassInfoVo;
import org.dromara.xg.domain.bo.XgClassInfoBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 班级信息Service接口
*
* @author Cursor AI
* @date 2025-01-21
*/
public interface IXgClassInfoService {
/**
* 查询班级信息
*
* @param id 班级信息主键
* @return 班级信息
*/
XgClassInfoVo queryById(Long id);
/**
* 查询班级信息列表
*
* @param bo 班级信息
* @return 班级信息集合
*/
TableDataInfo<XgClassInfoVo> queryPageList(XgClassInfoBo bo, PageQuery pageQuery);
/**
* 查询班级信息列表
*
* @param bo 班级信息
* @return 班级信息集合
*/
List<XgClassInfoVo> queryList(XgClassInfoBo bo);
/**
* 新增班级信息
*
* @param bo 班级信息
* @return 结果
*/
Boolean insertByBo(XgClassInfoBo bo);
/**
* 修改班级信息
*
* @param bo 班级信息
* @return 结果
*/
Boolean updateByBo(XgClassInfoBo bo);
/**
* 校验并批量删除班级信息信息
*
* @param ids 需要删除的班级信息主键集合
* @param isValid 是否校验,true-删除前校验,false-不校验
* @return 结果
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 根据班级代码查询班级信息
*
* @param classCode 班级代码
* @return 班级信息
*/
XgClassInfoVo queryByClassCode(String classCode);
/**
* 根据年级查询班级信息列表
*
* @param grade 年级
* @return 班级信息集合
*/
List<XgClassInfoVo> queryByGrade(String grade);
/**
* 根据学院代码查询班级信息列表
*
* @param collegeCode 学院代码
* @return 班级信息集合
*/
List<XgClassInfoVo> queryByCollegeCode(String collegeCode);
/**
* 根据专业代码查询班级信息列表
*
* @param majorCode 专业代码
* @return 班级信息集合
*/
List<XgClassInfoVo> queryByMajorCode(String majorCode);
/**
* 根据辅导员ID查询班级信息列表
*
* @param counselorId 辅导员ID
* @return 班级信息集合
*/
List<XgClassInfoVo> queryByCounselorId(Long counselorId);
/**
* 根据班主任ID查询班级信息列表
*
* @param classTeacherId 班主任ID
* @return 班级信息集合
*/
List<XgClassInfoVo> queryByClassTeacherId(Long classTeacherId);
/**
* 获取班级可用选项列表(用于下拉框)
*
* @return 班级选项集合
*/
List<XgClassInfoVo> getClassOptions();
/**
* 更新班级学生统计数据
*
* @param classId 班级ID
* @return 结果
*/
Boolean updateStudentCount(Long classId);
/**
* 批量更新班级学生统计数据
*
* @param classIds 班级ID集合
* @return 结果
*/
Boolean batchUpdateStudentCount(Collection<Long> classIds);
/**
* 启用班级
*
* @param id 班级ID
* @return 结果
*/
Boolean enableClass(Long id);
/**
* 禁用班级
*
* @param id 班级ID
* @return 结果
*/
Boolean disableClass(Long id);
// ================================
// 统计数据接口 - 新增
// ================================
/**
* 获取班级信息统计概览
*
* @return 统计概览数据
*/
Map<String, Object> getStatistics();
/**
* 统计各学院班级数量
*
* @return 学院班级数量统计
*/
List<Map<String, Object>> countByCollege();
/**
* 统计各年级班级数量
*
* @return 年级班级数量统计
*/
List<Map<String, Object>> countByGrade();
/**
* 统计各专业班级数量
*
* @return 专业班级数量统计
*/
List<Map<String, Object>> countByMajor();
/**
* 统计班级状态分布
*
* @return 班级状态统计
*/
List<Map<String, Object>> countByStatus();
}
@@ -0,0 +1,513 @@
package org.dromara.xg.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.dromara.xg.domain.bo.XgClassInfoBo;
import org.dromara.xg.domain.vo.XgClassInfoVo;
import org.dromara.xg.domain.XgClassInfo;
import org.dromara.xg.mapper.XgClassInfoMapper;
import org.dromara.xg.service.IXgClassInfoService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.ArrayList;
import java.util.HashMap;
import java.time.LocalDateTime;
/**
* 班级信息Service业务层处理
*
* @author Cursor AI
* @date 2025-01-21
*/
@RequiredArgsConstructor
@Service
public class XgClassInfoServiceImpl implements IXgClassInfoService {
private static final Logger log = LoggerFactory.getLogger(XgClassInfoServiceImpl.class);
private final XgClassInfoMapper baseMapper;
/**
* 查询班级信息
*/
@Override
public XgClassInfoVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 查询班级信息列表
*/
@Override
public TableDataInfo<XgClassInfoVo> queryPageList(XgClassInfoBo bo, PageQuery pageQuery) {
log.info("=== 班级信息分页查询开始 ===");
log.info("查询条件: {}", bo);
log.info("分页参数: {}", pageQuery);
// 构建查询条件
LambdaQueryWrapper<XgClassInfo> lqw = buildQueryWrapper(bo);
log.info("Service构建的Lambda查询条件: {}", lqw.getTargetSql());
// 执行分页查询
Page<XgClassInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
log.info("Mapper查询结果 - 总数: {}, 当前页记录数: {}", result.getTotal(), result.getRecords().size());
if (!result.getRecords().isEmpty()) {
log.info("第一条记录详情: {}", result.getRecords().get(0));
} else {
log.warn("Mapper查询结果为空!");
}
TableDataInfo<XgClassInfoVo> tableDataInfo = TableDataInfo.build(result);
log.info("最终返回结果 - 总数: {}, 行数: {}", tableDataInfo.getTotal(), tableDataInfo.getRows().size());
log.info("=== 班级信息分页查询结束 ===");
return tableDataInfo;
}
/**
* 查询班级信息列表
*/
@Override
public List<XgClassInfoVo> queryList(XgClassInfoBo bo) {
LambdaQueryWrapper<XgClassInfo> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<XgClassInfo> buildQueryWrapper(XgClassInfoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getClassCode()), XgClassInfo::getClassCode, bo.getClassCode());
lqw.like(StringUtils.isNotBlank(bo.getClassName()), XgClassInfo::getClassName, bo.getClassName());
lqw.eq(StringUtils.isNotBlank(bo.getClassType()), XgClassInfo::getClassType, bo.getClassType());
lqw.eq(StringUtils.isNotBlank(bo.getGrade()), XgClassInfo::getGrade, bo.getGrade());
lqw.eq(bo.getEnrollmentYear() != null, XgClassInfo::getEnrollmentYear, bo.getEnrollmentYear());
lqw.ge(bo.getEnrollmentYearStart() != null, XgClassInfo::getEnrollmentYear, bo.getEnrollmentYearStart());
lqw.le(bo.getEnrollmentYearEnd() != null, XgClassInfo::getEnrollmentYear, bo.getEnrollmentYearEnd());
lqw.eq(bo.getGraduationYear() != null, XgClassInfo::getGraduationYear, bo.getGraduationYear());
lqw.eq(StringUtils.isNotBlank(bo.getMajorCode()), XgClassInfo::getMajorCode, bo.getMajorCode());
lqw.like(StringUtils.isNotBlank(bo.getMajorName()), XgClassInfo::getMajorName, bo.getMajorName());
lqw.eq(StringUtils.isNotBlank(bo.getTrainingType()), XgClassInfo::getTrainingType, bo.getTrainingType());
lqw.eq(StringUtils.isNotBlank(bo.getDegreeType()), XgClassInfo::getDegreeType, bo.getDegreeType());
lqw.eq(StringUtils.isNotBlank(bo.getCollegeCode()), XgClassInfo::getCollegeCode, bo.getCollegeCode());
lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgClassInfo::getCollegeName, bo.getCollegeName());
lqw.eq(bo.getCounselorId() != null, XgClassInfo::getCounselorId, bo.getCounselorId());
lqw.like(StringUtils.isNotBlank(bo.getCounselorName()), XgClassInfo::getCounselorName, bo.getCounselorName());
lqw.eq(bo.getClassTeacherId() != null, XgClassInfo::getClassTeacherId, bo.getClassTeacherId());
lqw.like(StringUtils.isNotBlank(bo.getClassTeacherName()), XgClassInfo::getClassTeacherName, bo.getClassTeacherName());
lqw.eq(StringUtils.isNotBlank(bo.getClassStatus()), XgClassInfo::getClassStatus, bo.getClassStatus());
lqw.eq(bo.getIsGraduation() != null, XgClassInfo::getIsGraduation, bo.getIsGraduation());
// 批量查询条件
lqw.in(bo.getClassCodeList() != null && !bo.getClassCodeList().isEmpty(), XgClassInfo::getClassCode, bo.getClassCodeList());
lqw.in(bo.getClassStatusList() != null && !bo.getClassStatusList().isEmpty(), XgClassInfo::getClassStatus, bo.getClassStatusList());
lqw.in(bo.getCollegeCodeList() != null && !bo.getCollegeCodeList().isEmpty(), XgClassInfo::getCollegeCode, bo.getCollegeCodeList());
lqw.in(bo.getMajorCodeList() != null && !bo.getMajorCodeList().isEmpty(), XgClassInfo::getMajorCode, bo.getMajorCodeList());
lqw.in(bo.getGradeList() != null && !bo.getGradeList().isEmpty(), XgClassInfo::getGrade, bo.getGradeList());
lqw.in(bo.getCounselorIdList() != null && !bo.getCounselorIdList().isEmpty(), XgClassInfo::getCounselorId, bo.getCounselorIdList());
lqw.in(bo.getClassTeacherIdList() != null && !bo.getClassTeacherIdList().isEmpty(), XgClassInfo::getClassTeacherId, bo.getClassTeacherIdList());
// 时间范围查询
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
XgClassInfo::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
return lqw;
}
/**
* 新增班级信息
*/
@Override
public Boolean insertByBo(XgClassInfoBo bo) {
XgClassInfo add = MapstructUtils.convert(bo, XgClassInfo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改班级信息
*/
@Override
public Boolean updateByBo(XgClassInfoBo bo) {
XgClassInfo update = MapstructUtils.convert(bo, XgClassInfo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(XgClassInfo entity) {
// 校验班级代码唯一性
if (StringUtils.isNotBlank(entity.getClassCode())) {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getClassCode, entity.getClassCode());
lqw.ne(entity.getId() != null, XgClassInfo::getId, entity.getId());
XgClassInfo existEntity = baseMapper.selectOne(lqw);
if (existEntity != null) {
throw new RuntimeException("班级代码已存在,请重新输入");
}
}
// 设置默认值
if (entity.getClassType() == null) {
entity.setClassType("regular");
}
if (entity.getClassStatus() == null) {
entity.setClassStatus("1");
}
if (entity.getIsGraduation() == null) {
entity.setIsGraduation(0);
}
if (entity.getPlannedCapacity() == null) {
entity.setPlannedCapacity(50);
}
if (entity.getMaxStudentCount() == null) {
entity.setMaxStudentCount(entity.getPlannedCapacity());
}
if (entity.getCurrentStudentCount() == null) {
entity.setCurrentStudentCount(0);
}
if (entity.getMaleCount() == null) {
entity.setMaleCount(0);
}
if (entity.getFemaleCount() == null) {
entity.setFemaleCount(0);
}
if (entity.getActiveCount() == null) {
entity.setActiveCount(0);
}
if (entity.getTransferInCount() == null) {
entity.setTransferInCount(0);
}
if (entity.getTransferOutCount() == null) {
entity.setTransferOutCount(0);
}
if (entity.getDropoutCount() == null) {
entity.setDropoutCount(0);
}
if (entity.getGraduateCount() == null) {
entity.setGraduateCount(0);
}
}
/**
* 批量删除班级信息
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// 校验是否存在学生关联
// TODO: 添加学生关联校验逻辑
}
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 根据班级代码查询班级信息
*/
@Override
public XgClassInfoVo queryByClassCode(String classCode) {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getClassCode, classCode);
return baseMapper.selectVoOne(lqw);
}
/**
* 根据年级查询班级信息列表
*/
@Override
public List<XgClassInfoVo> queryByGrade(String grade) {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getGrade, grade);
lqw.eq(XgClassInfo::getClassStatus, "1");
lqw.orderByAsc(XgClassInfo::getClassCode);
return baseMapper.selectVoList(lqw);
}
/**
* 根据学院代码查询班级信息列表
*/
@Override
public List<XgClassInfoVo> queryByCollegeCode(String collegeCode) {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getCollegeCode, collegeCode);
lqw.eq(XgClassInfo::getClassStatus, "1");
lqw.orderByAsc(XgClassInfo::getGrade, XgClassInfo::getClassCode);
return baseMapper.selectVoList(lqw);
}
/**
* 根据专业代码查询班级信息列表
*/
@Override
public List<XgClassInfoVo> queryByMajorCode(String majorCode) {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getMajorCode, majorCode);
lqw.eq(XgClassInfo::getClassStatus, "1");
lqw.orderByAsc(XgClassInfo::getGrade, XgClassInfo::getClassCode);
return baseMapper.selectVoList(lqw);
}
/**
* 根据辅导员ID查询班级信息列表
*/
@Override
public List<XgClassInfoVo> queryByCounselorId(Long counselorId) {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getCounselorId, counselorId);
lqw.eq(XgClassInfo::getClassStatus, "1");
lqw.orderByAsc(XgClassInfo::getGrade, XgClassInfo::getClassCode);
return baseMapper.selectVoList(lqw);
}
/**
* 根据班主任ID查询班级信息列表
*/
@Override
public List<XgClassInfoVo> queryByClassTeacherId(Long classTeacherId) {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getClassTeacherId, classTeacherId);
lqw.eq(XgClassInfo::getClassStatus, "1");
lqw.orderByAsc(XgClassInfo::getGrade, XgClassInfo::getClassCode);
return baseMapper.selectVoList(lqw);
}
/**
* 获取班级可用选项列表(用于下拉框)
*/
@Override
public List<XgClassInfoVo> getClassOptions() {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getClassStatus, "1");
lqw.select(XgClassInfo::getId, XgClassInfo::getClassCode, XgClassInfo::getClassName,
XgClassInfo::getGrade, XgClassInfo::getMajorName, XgClassInfo::getCollegeName);
lqw.orderByAsc(XgClassInfo::getGrade, XgClassInfo::getClassCode);
return baseMapper.selectVoList(lqw);
}
/**
* 更新班级学生统计数据
*/
@Override
public Boolean updateStudentCount(Long classId) {
// TODO: 实现学生统计数据更新逻辑
// 1. 查询班级下的学生数量
// 2. 统计男女学生数量
// 3. 统计在籍学生数量
// 4. 更新班级统计字段
XgClassInfo classInfo = baseMapper.selectById(classId);
if (classInfo != null) {
classInfo.setLastCountUpdate(LocalDateTime.now());
return baseMapper.updateById(classInfo) > 0;
}
return false;
}
/**
* 批量更新班级学生统计数据
*/
@Override
public Boolean batchUpdateStudentCount(Collection<Long> classIds) {
boolean result = true;
for (Long classId : classIds) {
result = result && updateStudentCount(classId);
}
return result;
}
/**
* 启用班级
*/
@Override
public Boolean enableClass(Long id) {
XgClassInfo classInfo = baseMapper.selectById(id);
if (classInfo != null) {
classInfo.setClassStatus("1");
return baseMapper.updateById(classInfo) > 0;
}
return false;
}
/**
* 禁用班级
*/
@Override
public Boolean disableClass(Long id) {
XgClassInfo classInfo = baseMapper.selectById(id);
if (classInfo != null) {
classInfo.setClassStatus("0");
return baseMapper.updateById(classInfo) > 0;
}
return false;
}
// ================================
// 统计数据接口实现 - 新增
// ================================
/**
* 获取班级信息统计概览
*/
@Override
public Map<String, Object> getStatistics() {
Map<String, Object> result = new HashMap<>();
// 总班级数
LambdaQueryWrapper<XgClassInfo> totalLqw = Wrappers.lambdaQuery();
long totalCount = baseMapper.selectCount(totalLqw);
result.put("totalCount", totalCount);
// 正常班级数
LambdaQueryWrapper<XgClassInfo> activeLqw = Wrappers.lambdaQuery();
activeLqw.eq(XgClassInfo::getClassStatus, "1");
long activeCount = baseMapper.selectCount(activeLqw);
result.put("activeCount", activeCount);
// 暂停班级数
LambdaQueryWrapper<XgClassInfo> pausedLqw = Wrappers.lambdaQuery();
pausedLqw.eq(XgClassInfo::getClassStatus, "2");
long pausedCount = baseMapper.selectCount(pausedLqw);
result.put("pausedCount", pausedCount);
// 已毕业班级数
LambdaQueryWrapper<XgClassInfo> graduatedLqw = Wrappers.lambdaQuery();
graduatedLqw.eq(XgClassInfo::getClassStatus, "3");
long graduatedCount = baseMapper.selectCount(graduatedLqw);
result.put("graduatedCount", graduatedCount);
// 总学生数(统计当前学生数量字段的总和)
LambdaQueryWrapper<XgClassInfo> studentLqw = Wrappers.lambdaQuery();
studentLqw.select(XgClassInfo::getCurrentStudentCount);
List<XgClassInfo> classList = baseMapper.selectList(studentLqw);
long totalStudents = classList.stream()
.mapToLong(c -> c.getCurrentStudentCount() != null ? c.getCurrentStudentCount() : 0)
.sum();
result.put("totalStudents", totalStudents);
return result;
}
/**
* 统计各学院班级数量
*/
@Override
public List<Map<String, Object>> countByCollege() {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.select(XgClassInfo::getCollegeCode, XgClassInfo::getCollegeName)
.groupBy(XgClassInfo::getCollegeCode, XgClassInfo::getCollegeName);
List<XgClassInfo> list = baseMapper.selectList(lqw);
List<Map<String, Object>> result = new ArrayList<>();
for (XgClassInfo item : list) {
LambdaQueryWrapper<XgClassInfo> countLqw = Wrappers.lambdaQuery();
countLqw.eq(XgClassInfo::getCollegeCode, item.getCollegeCode());
long count = baseMapper.selectCount(countLqw);
Map<String, Object> map = new HashMap<>();
map.put("collegeCode", item.getCollegeCode());
map.put("collegeName", item.getCollegeName());
map.put("count", count);
result.add(map);
}
return result;
}
/**
* 统计各年级班级数量
*/
@Override
public List<Map<String, Object>> countByGrade() {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.select(XgClassInfo::getGrade)
.groupBy(XgClassInfo::getGrade);
List<XgClassInfo> list = baseMapper.selectList(lqw);
List<Map<String, Object>> result = new ArrayList<>();
for (XgClassInfo item : list) {
LambdaQueryWrapper<XgClassInfo> countLqw = Wrappers.lambdaQuery();
countLqw.eq(XgClassInfo::getGrade, item.getGrade());
long count = baseMapper.selectCount(countLqw);
Map<String, Object> map = new HashMap<>();
map.put("grade", item.getGrade());
map.put("count", count);
result.add(map);
}
return result;
}
/**
* 统计各专业班级数量
*/
@Override
public List<Map<String, Object>> countByMajor() {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.select(XgClassInfo::getMajorCode, XgClassInfo::getMajorName)
.groupBy(XgClassInfo::getMajorCode, XgClassInfo::getMajorName);
List<XgClassInfo> list = baseMapper.selectList(lqw);
List<Map<String, Object>> result = new ArrayList<>();
for (XgClassInfo item : list) {
LambdaQueryWrapper<XgClassInfo> countLqw = Wrappers.lambdaQuery();
countLqw.eq(XgClassInfo::getMajorCode, item.getMajorCode());
long count = baseMapper.selectCount(countLqw);
Map<String, Object> map = new HashMap<>();
map.put("majorCode", item.getMajorCode());
map.put("majorName", item.getMajorName());
map.put("count", count);
result.add(map);
}
return result;
}
/**
* 统计班级状态分布
*/
@Override
public List<Map<String, Object>> countByStatus() {
List<Map<String, Object>> result = new ArrayList<>();
// 状态码对应的名称
String[] statusCodes = {"1", "2", "3", "4"};
String[] statusNames = {"正常", "暂停", "毕业", "解散"};
for (int i = 0; i < statusCodes.length; i++) {
LambdaQueryWrapper<XgClassInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(XgClassInfo::getClassStatus, statusCodes[i]);
long count = baseMapper.selectCount(lqw);
Map<String, Object> map = new HashMap<>();
map.put("statusCode", statusCodes[i]);
map.put("statusName", statusNames[i]);
map.put("count", count);
result.add(map);
}
return result;
}
}
@@ -0,0 +1,239 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.xg.mapper.XgClassInfoMapper">
<resultMap type="org.dromara.xg.domain.vo.XgClassInfoVo" id="XgClassInfoVoResult">
<result property="id" column="id"/>
<result property="classCode" column="class_code"/>
<result property="className" column="class_name"/>
<result property="classType" column="class_type"/>
<result property="grade" column="grade"/>
<result property="enrollmentYear" column="enrollment_year"/>
<result property="graduationYear" column="graduation_year"/>
<result property="majorCode" column="major_code"/>
<result property="majorName" column="major_name"/>
<result property="trainingType" column="training_type"/>
<result property="degreeType" column="degree_type"/>
<result property="collegeCode" column="college_code"/>
<result property="collegeName" column="college_name"/>
<result property="counselorId" column="counselor_id"/>
<result property="counselorName" column="counselor_name"/>
<result property="classTeacherId" column="class_teacher_id"/>
<result property="classTeacherName" column="class_teacher_name"/>
<result property="classAdvisorId" column="class_advisor_id"/>
<result property="classAdvisorName" column="class_advisor_name"/>
<result property="classMonitorId" column="class_monitor_id"/>
<result property="classMonitorName" column="class_monitor_name"/>
<result property="deputyMonitorId" column="deputy_monitor_id"/>
<result property="deputyMonitorName" column="deputy_monitor_name"/>
<result property="classStatus" column="class_status"/>
<result property="isGraduation" column="is_graduation"/>
<result property="graduationDate" column="graduation_date"/>
<result property="plannedCapacity" column="planned_capacity"/>
<result property="currentStudentCount" column="current_student_count"/>
<result property="maxStudentCount" column="max_student_count"/>
<result property="maleCount" column="male_count"/>
<result property="femaleCount" column="female_count"/>
<result property="activeCount" column="active_count"/>
<result property="transferInCount" column="transfer_in_count"/>
<result property="transferOutCount" column="transfer_out_count"/>
<result property="dropoutCount" column="dropout_count"/>
<result property="graduateCount" column="graduate_count"/>
<result property="officeLocation" column="office_location"/>
<result property="classLocation" column="class_location"/>
<result property="contactPhone" column="contact_phone"/>
<result property="qqGroup" column="qq_group"/>
<result property="wechatGroup" column="wechat_group"/>
<result property="email" column="email"/>
<result property="classSchedule" column="class_schedule"/>
<result property="classCulture" column="class_culture"/>
<result property="classRules" column="class_rules"/>
<result property="classDescription" column="class_description"/>
<result property="lastCountUpdate" column="last_count_update"/>
<result property="extField1" column="ext_field1"/>
<result property="extField2" column="ext_field2"/>
<result property="extField3" column="ext_field3"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<!-- 自定义分页查询方法 - 移除tenant_id字段查询,但保留WHERE条件 -->
<select id="selectVoPage" resultMap="XgClassInfoVoResult">
<!-- 调试信息:开始执行班级信息自定义分页查询 -->
SELECT
id, class_code, class_name, class_type, grade, enrollment_year, graduation_year,
major_code, major_name, training_type, degree_type, college_code, college_name,
counselor_id, counselor_name, class_teacher_id, class_teacher_name,
class_advisor_id, class_advisor_name, class_monitor_id, class_monitor_name,
deputy_monitor_id, deputy_monitor_name, class_status, is_graduation, graduation_date,
planned_capacity, current_student_count, max_student_count, male_count, female_count,
active_count, transfer_in_count, transfer_out_count, dropout_count, graduate_count,
office_location, class_location, contact_phone, qq_group, wechat_group, email,
class_schedule, class_culture, class_rules, class_description, last_count_update,
ext_field1, ext_field2, ext_field3, remark,
create_by, create_time, update_by, update_time
FROM xg_class_info
WHERE deleted = 0 AND tenant_id = '000000'
<if test="ew != null and ew.sqlSegment != null and ew.sqlSegment != '' and !ew.sqlSegment.trim().toUpperCase().startsWith('ORDER BY')">
AND ${ew.sqlSegment}
</if>
<if test="ew != null and ew.sqlSegment != null and ew.sqlSegment != '' and ew.sqlSegment.trim().toUpperCase().startsWith('ORDER BY')">
${ew.sqlSegment}
</if>
</select>
<!-- 自定义详情查询方法 - 移除tenant_id字段查询,但保留WHERE条件 -->
<select id="selectVoById" parameterType="java.io.Serializable" resultMap="XgClassInfoVoResult">
SELECT
id, class_code, class_name, class_type, grade, enrollment_year, graduation_year,
major_code, major_name, training_type, degree_type, college_code, college_name,
counselor_id, counselor_name, class_teacher_id, class_teacher_name,
class_advisor_id, class_advisor_name, class_monitor_id, class_monitor_name,
deputy_monitor_id, deputy_monitor_name, class_status, is_graduation, graduation_date,
planned_capacity, current_student_count, max_student_count, male_count, female_count,
active_count, transfer_in_count, transfer_out_count, dropout_count, graduate_count,
office_location, class_location, contact_phone, qq_group, wechat_group, email,
class_schedule, class_culture, class_rules, class_description, last_count_update,
ext_field1, ext_field2, ext_field3, remark,
create_by, create_time, update_by, update_time
FROM xg_class_info
WHERE id = #{id}
AND deleted = 0
AND tenant_id = '000000'
</select>
<sql id="selectXgClassInfoVo">
select id, class_code, class_name, class_type, grade, enrollment_year, graduation_year,
major_code, major_name, training_type, degree_type, college_code, college_name,
counselor_id, counselor_name, class_teacher_id, class_teacher_name,
class_advisor_id, class_advisor_name, class_monitor_id, class_monitor_name,
deputy_monitor_id, deputy_monitor_name, class_status, is_graduation, graduation_date,
planned_capacity, current_student_count, max_student_count, male_count, female_count,
active_count, transfer_in_count, transfer_out_count, dropout_count, graduate_count,
office_location, class_location, contact_phone, qq_group, wechat_group, email,
class_schedule, class_culture, class_rules, class_description, last_count_update,
ext_field1, ext_field2, ext_field3, remark, create_by, create_time, update_by, update_time
from xg_class_info
</sql>
<!-- 根据班级代码查询班级信息 -->
<select id="selectByClassCode" parameterType="String" resultMap="XgClassInfoVoResult">
SELECT * FROM xg_class_info
WHERE class_code = #{classCode}
AND deleted = 0
AND tenant_id = '000000'
</select>
<!-- 查询指定年级的班级列表 -->
<select id="selectByGrade" parameterType="String" resultMap="XgClassInfoVoResult">
SELECT * FROM xg_class_info
WHERE grade = #{grade}
AND deleted = 0
AND tenant_id = '000000'
AND class_status = '1'
ORDER BY class_code
</select>
<!-- 查询指定学院的班级列表 -->
<select id="selectByCollegeCode" parameterType="String" resultMap="XgClassInfoVoResult">
SELECT * FROM xg_class_info
WHERE college_code = #{collegeCode}
AND deleted = 0
AND tenant_id = '000000'
AND class_status = '1'
ORDER BY grade, class_code
</select>
<!-- 查询指定专业的班级列表 -->
<select id="selectByMajorCode" parameterType="String" resultMap="XgClassInfoVoResult">
SELECT * FROM xg_class_info
WHERE major_code = #{majorCode}
AND deleted = 0
AND tenant_id = '000000'
AND class_status = '1'
ORDER BY grade, class_code
</select>
<!-- 查询指定辅导员的班级列表 -->
<select id="selectByCounselorId" parameterType="Long" resultMap="XgClassInfoVoResult">
SELECT * FROM xg_class_info
WHERE counselor_id = #{counselorId}
AND deleted = 0
AND tenant_id = '000000'
AND class_status = '1'
ORDER BY grade, class_code
</select>
<!-- 查询指定班主任的班级列表 -->
<select id="selectByClassTeacherId" parameterType="Long" resultMap="XgClassInfoVoResult">
SELECT * FROM xg_class_info
WHERE class_teacher_id = #{classTeacherId}
AND deleted = 0
AND tenant_id = '000000'
AND class_status = '1'
ORDER BY grade, class_code
</select>
<!-- 统计各学院班级数量 -->
<select id="countByCollege" resultType="java.util.Map">
SELECT
college_code,
college_name,
COUNT(*) as count
FROM xg_class_info
WHERE deleted = 0
AND tenant_id = '000000'
GROUP BY college_code, college_name
ORDER BY count DESC
</select>
<!-- 统计各年级班级数量 -->
<select id="countByGrade" resultType="java.util.Map">
SELECT
grade,
COUNT(*) as count
FROM xg_class_info
WHERE deleted = 0
AND tenant_id = '000000'
GROUP BY grade
ORDER BY grade
</select>
<!-- 统计各专业班级数量 -->
<select id="countByMajor" resultType="java.util.Map">
SELECT
major_code,
major_name,
COUNT(*) as count
FROM xg_class_info
WHERE deleted = 0
AND tenant_id = '000000'
GROUP BY major_code, major_name
ORDER BY count DESC
</select>
<!-- 统计班级状态分布 -->
<select id="countByClassStatus" resultType="java.util.Map">
SELECT
class_status,
CASE
WHEN class_status = '1' THEN '正常'
WHEN class_status = '2' THEN '暂停'
WHEN class_status = '3' THEN '毕业'
WHEN class_status = '4' THEN '解散'
ELSE '未知'
END as status_name,
COUNT(*) as count
FROM xg_class_info
WHERE deleted = 0
AND tenant_id = '000000'
GROUP BY class_status
ORDER BY class_status
</select>
</mapper>
+287
View File
@@ -0,0 +1,287 @@
import request from '@/utils/request'
import { AxiosPromise } from 'axios'
import { ClassInfoVO, ClassInfoQuery, ClassInfoForm, OptionData } from './classInfo/types'
// 通用类型定义
interface TableDataInfo<T> {
code: number;
msg: string;
rows: T[];
total: number;
}
interface R<T> {
code: number;
msg: string;
data: T;
}
/**
* 查询班级信息列表
*/
export const listClassInfo = (query: ClassInfoQuery): AxiosPromise<TableDataInfo<ClassInfoVO>> => {
return request({
url: '/xg/classInfo/list',
method: 'get',
params: query
})
}
/**
* 查询班级信息详细
*/
export const getClassInfo = (id: string | number): AxiosPromise<R<ClassInfoVO>> => {
return request({
url: '/xg/classInfo/' + id,
method: 'get'
})
}
/**
* 新增班级信息
*/
export const addClassInfo = (data: ClassInfoForm): AxiosPromise<R<void>> => {
return request({
url: '/xg/classInfo',
method: 'post',
data: data
})
}
/**
* 修改班级信息
*/
export const updateClassInfo = (data: ClassInfoForm): AxiosPromise<R<void>> => {
return request({
url: '/xg/classInfo',
method: 'put',
data: data
})
}
/**
* 删除班级信息
*/
export const delClassInfo = (id: string | number | Array<string | number>): AxiosPromise<R<void>> => {
return request({
url: '/xg/classInfo/' + id,
method: 'delete'
})
}
/**
* 导出班级信息
*/
export const exportClassInfo = (query: ClassInfoQuery): AxiosPromise<any> => {
return request({
url: '/xg/classInfo/export',
method: 'post',
data: query
})
}
/**
* 根据班级代码查询班级信息
*/
export const getClassInfoByCode = (classCode: string): AxiosPromise<R<ClassInfoVO>> => {
return request({
url: '/xg/classInfo/getByClassCode/' + classCode,
method: 'get'
})
}
/**
* 根据年级查询班级信息列表
*/
export const getClassInfoByGrade = (grade: string): AxiosPromise<R<ClassInfoVO[]>> => {
return request({
url: '/xg/classInfo/getByGrade/' + grade,
method: 'get'
})
}
/**
* 根据学院代码查询班级信息列表
*/
export const getClassInfoByCollege = (collegeCode: string): AxiosPromise<R<ClassInfoVO[]>> => {
return request({
url: '/xg/classInfo/getByCollegeCode/' + collegeCode,
method: 'get'
})
}
/**
* 根据专业代码查询班级信息列表
*/
export const getClassInfoByMajor = (majorCode: string): AxiosPromise<R<ClassInfoVO[]>> => {
return request({
url: '/xg/classInfo/getByMajorCode/' + majorCode,
method: 'get'
})
}
/**
* 根据辅导员ID查询班级信息列表
*/
export const getClassInfoByCounselor = (counselorId: number): AxiosPromise<R<ClassInfoVO[]>> => {
return request({
url: '/xg/classInfo/getByCounselorId/' + counselorId,
method: 'get'
})
}
/**
* 根据班主任ID查询班级信息列表
*/
export const getClassInfoByClassTeacher = (classTeacherId: number): AxiosPromise<R<ClassInfoVO[]>> => {
return request({
url: '/xg/classInfo/getByClassTeacherId/' + classTeacherId,
method: 'get'
})
}
/**
* 获取班级选项列表(用于下拉框)
*/
export const getClassOptions = (): AxiosPromise<R<ClassInfoVO[]>> => {
return request({
url: '/xg/classInfo/getClassOptions', // 修正路径:从 /options 改为 /getClassOptions
method: 'get'
})
}
/**
* 更新班级学生统计
*/
export const updateStudentCount = (classId: number): AxiosPromise<R<void>> => {
return request({
url: '/xg/classInfo/updateStudentCount/' + classId,
method: 'post' // 修正HTTP方法:从 put 改为 post
})
}
/**
* 批量更新班级学生统计
*/
export const batchUpdateStudentCount = (classIds: number[]): AxiosPromise<R<void>> => {
return request({
url: '/xg/classInfo/batchUpdateStudentCount',
method: 'post', // 修正HTTP方法:从 put 改为 post
data: classIds
})
}
/**
* 启用班级
*/
export const enableClass = (id: number): AxiosPromise<R<void>> => {
return request({
url: '/xg/classInfo/enable/' + id,
method: 'post' // 修正HTTP方法:从 put 改为 post
})
}
/**
* 禁用班级
*/
export const disableClass = (id: number): AxiosPromise<R<void>> => {
return request({
url: '/xg/classInfo/disable/' + id,
method: 'post' // 修正HTTP方法:从 put 改为 post
})
}
// ================================
// 统计数据接口 - 新增
// ================================
/**
* 获取班级信息统计概览
*/
export const getClassStatistics = (): AxiosPromise<R<any>> => {
return request({
url: '/xg/classInfo/statistics',
method: 'get'
})
}
/**
* 统计各学院班级数量
*/
export const countClassByCollege = (): AxiosPromise<R<any[]>> => {
return request({
url: '/xg/classInfo/statistics/college',
method: 'get'
})
}
/**
* 统计各年级班级数量
*/
export const countClassByGrade = (): AxiosPromise<R<any[]>> => {
return request({
url: '/xg/classInfo/statistics/grade',
method: 'get'
})
}
/**
* 统计各专业班级数量
*/
export const countClassByMajor = (): AxiosPromise<R<any[]>> => {
return request({
url: '/xg/classInfo/statistics/major',
method: 'get'
})
}
/**
* 统计班级状态分布
*/
export const countClassByStatus = (): AxiosPromise<R<any[]>> => {
return request({
url: '/xg/classInfo/statistics/status',
method: 'get'
})
}
/**
* 获取学院选项
*/
export const getCollegeOptions = (): AxiosPromise<R<any[]>> => {
return request({
url: '/xg/studentInfo/options/colleges',
method: 'get'
})
}
/**
* 获取专业选项
*/
export const getMajorOptions = (collegeCode?: string): AxiosPromise<R<any[]>> => {
return request({
url: '/xg/studentInfo/options/majors',
method: 'get',
params: { collegeCode }
})
}
/**
* 获取辅导员选项
*/
export const getCounselorOptions = (): AxiosPromise<R<any[]>> => {
return request({
url: '/xg/studentInfo/options/counselors',
method: 'get'
})
}
/**
* 获取班主任选项
*/
export const getClassTeacherOptions = (): AxiosPromise<R<any[]>> => {
return request({
url: '/xg/studentInfo/options/classTeachers',
method: 'get'
})
}
+786
View File
@@ -0,0 +1,786 @@
/**
* 班级信息管理模块 - 类型定义
*/
/**
* 班级信息 VO
*/
export interface ClassInfoVO {
/**
* 主键ID
*/
id: string | number;
/**
* 租户编号
*/
tenantId?: string;
/**
* 班级代码
*/
classCode: string;
/**
* 班级名称
*/
className: string;
/**
* 班级类型:regular-普通班级,honor-荣誉班级,experimental-实验班级,special-特殊班级
*/
classType?: string;
/**
* 年级
*/
grade: string;
/**
* 入学年份
*/
enrollmentYear: number;
/**
* 毕业年份
*/
graduationYear?: number;
/**
* 专业代码
*/
majorCode?: string;
/**
* 专业名称
*/
majorName?: string;
/**
* 培养方式:全日制、在职、函授、夜大等
*/
trainingType?: string;
/**
* 学位类型:本科、专科、研究生等
*/
degreeType?: string;
/**
* 学院代码
*/
collegeCode?: string;
/**
* 学院名称
*/
collegeName?: string;
/**
* 辅导员ID
*/
counselorId?: string | number;
/**
* 辅导员姓名
*/
counselorName?: string;
/**
* 班主任ID
*/
classTeacherId?: string | number;
/**
* 班主任姓名
*/
classTeacherName?: string;
/**
* 班级导师ID
*/
classAdvisorId?: string | number;
/**
* 班级导师姓名
*/
classAdvisorName?: string;
/**
* 班长ID
*/
classMonitorId?: string | number;
/**
* 班长姓名
*/
classMonitorName?: string;
/**
* 副班长ID
*/
deputyMonitorId?: string | number;
/**
* 副班长姓名
*/
deputyMonitorName?: string;
/**
* 班级状态:1-正常,2-暂停,3-毕业,4-解散
*/
classStatus?: string;
/**
* 是否毕业:0-未毕业,1-已毕业
*/
isGraduation?: number;
/**
* 毕业日期
*/
graduationDate?: string;
/**
* 计划容量
*/
plannedCapacity?: number;
/**
* 当前学生数量
*/
currentStudentCount?: number;
/**
* 最大学生数量
*/
maxStudentCount?: number;
/**
* 男生数量
*/
maleCount?: number;
/**
* 女生数量
*/
femaleCount?: number;
/**
* 在籍学生数量
*/
activeCount?: number;
/**
* 转入学生数量
*/
transferInCount?: number;
/**
* 转出学生数量
*/
transferOutCount?: number;
/**
* 退学学生数量
*/
dropoutCount?: number;
/**
* 毕业学生数量
*/
graduateCount?: number;
/**
* 办公室位置
*/
officeLocation?: string;
/**
* 教室位置
*/
classLocation?: string;
/**
* 联系电话
*/
contactPhone?: string;
/**
* QQ群号
*/
qqGroup?: string;
/**
* 微信群
*/
wechatGroup?: string;
/**
* 邮箱
*/
email?: string;
/**
* 课程安排
*/
classSchedule?: string;
/**
* 班级文化
*/
classCulture?: string;
/**
* 班级规章制度
*/
classRules?: string;
/**
* 班级描述
*/
classDescription?: string;
/**
* 最后统计更新时间
*/
lastCountUpdate?: string;
/**
* 扩展字段1
*/
extField1?: string;
/**
* 扩展字段2
*/
extField2?: string;
/**
* 扩展字段3
*/
extField3?: string;
/**
* 备注
*/
remark?: string;
/**
* 创建者
*/
createBy?: string | number;
/**
* 创建时间
*/
createTime?: string;
/**
* 更新者
*/
updateBy?: string | number;
/**
* 更新时间
*/
updateTime?: string;
}
/**
* 班级信息查询对象
*/
export interface ClassInfoQuery {
/**
* 当前页数
*/
pageNum?: number;
/**
* 每页显示记录数
*/
pageSize?: number;
/**
* 班级代码
*/
classCode?: string;
/**
* 班级名称
*/
className?: string;
/**
* 班级类型
*/
classType?: string;
/**
* 年级
*/
grade?: string;
/**
* 入学年份
*/
enrollmentYear?: number;
/**
* 毕业年份
*/
graduationYear?: number;
/**
* 学院代码
*/
collegeCode?: string;
/**
* 学院名称
*/
collegeName?: string;
/**
* 专业代码
*/
majorCode?: string;
/**
* 专业名称
*/
majorName?: string;
/**
* 班主任ID
*/
classTeacherId?: string | number;
/**
* 班主任姓名
*/
classTeacherName?: string;
/**
* 辅导员ID
*/
counselorId?: string | number;
/**
* 辅导员姓名
*/
counselorName?: string;
/**
* 班级状态
*/
classStatus?: string;
/**
* 班级代码列表(批量查询)
*/
classCodeList?: string[];
/**
* 班级状态列表(批量查询)
*/
classStatusList?: string[];
/**
* 入学年份开始
*/
enrollmentYearStart?: number;
/**
* 入学年份结束
*/
enrollmentYearEnd?: number;
/**
* 创建时间开始
*/
createTimeStart?: string;
/**
* 创建时间结束
*/
createTimeEnd?: string;
}
/**
* 班级信息表单对象
*/
export interface ClassInfoForm {
/**
* 主键ID
*/
id?: string | number;
/**
* 班级代码
*/
classCode?: string;
/**
* 班级名称
*/
className?: string;
/**
* 班级类型
*/
classType?: string;
/**
* 年级
*/
grade?: string;
/**
* 入学年份
*/
enrollmentYear?: number;
/**
* 毕业年份
*/
graduationYear?: number;
/**
* 专业代码
*/
majorCode?: string;
/**
* 专业名称
*/
majorName?: string;
/**
* 培养方式
*/
trainingType?: string;
/**
* 学位类型
*/
degreeType?: string;
/**
* 学院代码
*/
collegeCode?: string;
/**
* 学院名称
*/
collegeName?: string;
/**
* 辅导员ID
*/
counselorId?: string | number;
/**
* 辅导员姓名
*/
counselorName?: string;
/**
* 班主任ID
*/
classTeacherId?: string | number;
/**
* 班主任姓名
*/
classTeacherName?: string;
/**
* 班级导师ID
*/
classAdvisorId?: string | number;
/**
* 班级导师姓名
*/
classAdvisorName?: string;
/**
* 班长ID
*/
classMonitorId?: string | number;
/**
* 班长姓名
*/
classMonitorName?: string;
/**
* 副班长ID
*/
deputyMonitorId?: string | number;
/**
* 副班长姓名
*/
deputyMonitorName?: string;
/**
* 班级状态
*/
classStatus?: string;
/**
* 是否毕业
*/
isGraduation?: number;
/**
* 毕业日期
*/
graduationDate?: string;
/**
* 计划容量
*/
plannedCapacity?: number;
/**
* 当前学生数量
*/
currentStudentCount?: number;
/**
* 最大学生数量
*/
maxStudentCount?: number;
/**
* 男生数量
*/
maleCount?: number;
/**
* 女生数量
*/
femaleCount?: number;
/**
* 在籍学生数量
*/
activeCount?: number;
/**
* 转入学生数量
*/
transferInCount?: number;
/**
* 转出学生数量
*/
transferOutCount?: number;
/**
* 退学学生数量
*/
dropoutCount?: number;
/**
* 毕业学生数量
*/
graduateCount?: number;
/**
* 办公室位置
*/
officeLocation?: string;
/**
* 教室位置
*/
classLocation?: string;
/**
* 联系电话
*/
contactPhone?: string;
/**
* QQ群号
*/
qqGroup?: string;
/**
* 微信群
*/
wechatGroup?: string;
/**
* 邮箱
*/
email?: string;
/**
* 课程安排
*/
classSchedule?: string;
/**
* 班级文化
*/
classCulture?: string;
/**
* 班级规章制度
*/
classRules?: string;
/**
* 班级描述
*/
classDescription?: string;
/**
* 最后统计更新时间
*/
lastCountUpdate?: string;
/**
* 扩展字段1
*/
extField1?: string;
/**
* 扩展字段2
*/
extField2?: string;
/**
* 扩展字段3
*/
extField3?: string;
/**
* 备注
*/
remark?: string;
}
/**
* 班级统计数据
*/
export interface ClassStatisticsData {
/**
* 总班级数
*/
totalCount: number;
/**
* 正常班级数
*/
activeCount: number;
/**
* 已毕业班级数
*/
graduatedCount: number;
/**
* 暂停班级数
*/
suspendedCount: number;
/**
* 解散班级数
*/
dissolvedCount: number;
/**
* 总学生数
*/
totalStudentCount: number;
/**
* 平均班级人数
*/
averageClassSize: number;
}
/**
* 班级选项数据
*/
export interface OptionData {
/**
* 值
*/
value: string | number;
/**
* 标签
*/
label: string;
/**
* 是否禁用
*/
disabled?: boolean;
/**
* 扩展数据
*/
data?: any;
}
/**
* 班级图表数据
*/
export interface ClassChartData {
/**
* 类别
*/
category: string;
/**
* 数值
*/
value: number;
/**
* 颜色
*/
color?: string;
/**
* 百分比
*/
percentage?: number;
}
/**
* 批量操作结果
*/
export interface BatchOperationResult {
/**
* 总数
*/
total: number;
/**
* 成功数
*/
success: number;
/**
* 失败数
*/
failed: number;
/**
* 失败的记录
*/
failedRecords?: Array<{
id: string | number;
reason: string;
}>;
}
+217
View File
@@ -0,0 +1,217 @@
# 班级信息管理模块
## 📋 模块说明
- **模块名称**: 班级信息管理 (Class Information Management)
- **模块简称**: classInfo
- **对应后端**: backend/ruoyi-modules/ruoyi-xg-xx/
- **对应API**: web/src/api/xg-xx/classInfo.ts
## 🎯 功能概述
班级信息管理模块提供完整的班级信息管理功能,包括:
### 📊 统计概览
- 总班级数统计
- 正常班级数统计
- 总学生数统计
- 平均学生数统计
### 🔍 查询功能
- 班级代码、班级名称模糊查询
- 年级、学院、专业级联查询
- 班级类型、班级状态筛选
- 班主任姓名查询
### 📝 基础管理
- 班级信息新增、修改、删除
- 班级信息详情查看
- 班级信息批量导出
### 👥 人员配置
- 班主任、辅导员配置
- 班干部信息管理(班长、学习委员、生活委员等)
- 联系方式管理
### 📈 统计功能
- 学生数量统计更新
- 批量统计刷新
- 实时数据同步
## 🎨 页面设计
### 页面布局
- **搜索区域**: 8个搜索条件,支持组合查询
- **统计卡片**: 4个统计指标,渐变色彩设计
- **表格区域**: 完整的班级信息展示
- **操作按钮**: 查看、编辑、删除、统计更新
### 对话框设计
- **新增/编辑**: 分页签设计(基本信息、人员配置、联系方式)
- **详情查看**: 描述列表展示完整信息
- **响应式布局**: 适配不同屏幕尺寸
## 🔧 技术特性
### 前端技术
- **Vue 3.5.13** + **TypeScript 5.8.3**
- **Element Plus** UI组件库
- **Composition API** 组合式API
- **响应式设计** 适配多端
### 样式设计
- **参考后勤管理模块** 保持风格一致
- **渐变色卡片** 美观的统计展示
- **悬停效果** 良好的交互体验
- **操作按钮** 图标化设计
### 数据处理
- **级联选择** 学院-专业联动
- **表单验证** 完整的输入校验
- **状态管理** 响应式数据更新
- **错误处理** 友好的错误提示
## 📋 API接口
### 16个标准API接口
#### 基础CRUD接口
1. `GET /list` - 查询班级信息列表
2. `POST /export` - 导出班级信息列表
3. `GET /{id}` - 获取班级信息详情
4. `POST /` - 新增班级信息
5. `PUT /` - 修改班级信息
6. `DELETE /{ids}` - 删除班级信息
#### 业务查询接口
7. `GET /getByClassCode/{classCode}` - 根据班级代码查询
8. `GET /getByGrade/{grade}` - 根据年级查询
9. `GET /getByCollegeCode/{collegeCode}` - 根据学院代码查询
10. `GET /getByMajorCode/{majorCode}` - 根据专业代码查询
11. `GET /getByCounselorId/{counselorId}` - 根据辅导员ID查询
12. `GET /getByClassTeacherId/{classTeacherId}` - 根据班主任ID查询
#### 辅助功能接口
13. `GET /getClassOptions` - 获取班级选项列表
14. `POST /updateStudentCount/{id}` - 更新班级学生统计
15. `POST /batchUpdateStudentCount` - 批量更新学生统计
16. `POST /enable/{id}` 和 `POST /disable/{id}` - 启用/禁用班级
## 🎯 权限控制
### 权限编码
- `xg:classInfo:list` - 班级信息查询
- `xg:classInfo:query` - 班级信息详情
- `xg:classInfo:add` - 班级信息新增
- `xg:classInfo:edit` - 班级信息修改
- `xg:classInfo:remove` - 班级信息删除
- `xg:classInfo:export` - 班级信息导出
### 按钮权限
- 所有操作按钮都配置了对应的权限控制
- 使用 `v-hasPermi` 指令进行权限验证
- 无权限时自动隐藏相关按钮
## 📊 数据字典
### 班级类型 (xg_class_type)
- `regular` - 普通班级
- `honor` - 荣誉班级
- `experimental` - 实验班级
- `special` - 特殊班级
### 班级状态 (xg_class_status)
- `1` - 正常
- `2` - 暂停
- `3` - 毕业
- `4` - 解散
### 年级选项 (xg_grade_options)
- 支持动态配置年级选项
- 适配不同学制需求
## 🔄 数据流程
### 查询流程
1. 用户输入查询条件
2. 前端组装查询参数
3. 调用列表查询API
4. 后端返回分页数据
5. 前端渲染表格和统计
### 新增/修改流程
1. 用户填写表单信息
2. 前端表单验证
3. 调用新增/修改API
4. 后端业务处理
5. 返回操作结果
6. 刷新列表和统计
### 统计更新流程
1. 用户点击统计更新
2. 调用统计更新API
3. 后端重新计算学生数
4. 更新班级统计信息
5. 返回最新统计数据
## 🎨 样式规范
### 色彩设计
- **主色调**: 蓝色系 (#409eff)
- **统计卡片**: 渐变色设计
- **状态标签**: 语义化颜色
- **交互效果**: 悬停和点击反馈
### 布局规范
- **页面间距**: 8px 外边距
- **组件间距**: 10px 组件间距
- **表格样式**: 斑马纹和悬停效果
- **按钮样式**: 图标化小按钮
### 响应式设计
- **搜索区域**: 4列布局,支持响应式
- **统计卡片**: 4列布局,移动端自适应
- **表格列**: 固定宽度和自适应结合
- **对话框**: 固定宽度,内容自适应
## 📝 使用说明
### 基本操作
1. **查询班级**: 使用搜索条件筛选班级信息
2. **新增班级**: 点击"新增班级"按钮,填写班级信息
3. **修改班级**: 点击表格行的"编辑"按钮
4. **查看详情**: 双击表格行或点击"查看"按钮
5. **删除班级**: 选择班级后点击"删除"按钮
### 高级功能
1. **批量操作**: 选择多个班级进行批量删除
2. **导出数据**: 根据查询条件导出Excel文件
3. **统计更新**: 手动更新班级学生统计数据
4. **级联查询**: 学院-专业联动查询
### 注意事项
- 班级代码必须唯一,系统会自动校验
- 删除班级前请确认该班级下无学生信息
- 统计数据会定期自动更新,也可手动刷新
- 导出功能会根据当前查询条件生成文件
## 🚀 扩展功能
### 计划功能
- 班级学生管理集成
- 班级活动管理
- 班级成绩统计
- 班级考勤管理
### 技术优化
- 虚拟滚动优化大数据量
- 缓存机制提升查询性能
- 实时数据推送
- 移动端适配优化
---
**📅 创建时间**: 2025-01-01
**👨‍💻 开发者**: Cursor AI
**📝 版本**: v1.0.0
**🔄 更新**: 持续迭代中
File diff suppressed because it is too large. Load diff