feat: 🎸 excel导入学生

This commit is contained in:
GoCo 2025-09-08 17:04:53 +08:00
parent 461bbaec56
commit 2824d20fc1
4 changed files with 176 additions and 15 deletions

View File

@ -2,46 +2,34 @@ package org.jeecg.modules.aiol.controller;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.aiol.entity.AiolClass;
import org.jeecg.modules.aiol.entity.AiolClassStudent;
import org.jeecg.modules.aiol.service.IAiolClassService;
import org.jeecg.modules.aiol.service.IAiolClassStudentService;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.system.service.ISysUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog;
@ -66,6 +54,8 @@ public class AiolClassController extends JeecgController<AiolClass, IAiolClassSe
private ISysBaseAPI sysBaseApi;
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private ISysUserService sysUserService;
/**
* 分页列表查询
@ -325,4 +315,124 @@ public class AiolClassController extends JeecgController<AiolClass, IAiolClassSe
return Result.error("移除学生失败: " + e.getMessage());
}
}
/**
* 导入学生到班级通过Excel
*
* @param classId 班级ID
* @param request HTTP请求对象
* @return
*/
@AutoLog(value = "班级学生-导入学生")
@Operation(summary = "导入学生到班级", description = "通过Excel文件导入学生到指定班级如果学生不存在则自动创建")
@PostMapping(value = "/{classId}/import_students_excel")
public Result<Map<String, Object>> importStudentsToClassByExcel(
@PathVariable("classId") String classId,
HttpServletRequest request) {
try {
// 1. 获取当前登录用户信息
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
String username = JwtUtil.getUsername(token);
LoginUser sysUser = sysBaseApi.getUserByName(username);
if (sysUser == null) {
return Result.error("用户未登录或登录已过期");
}
// 2. 模拟Excel数据暂时不实现Excel解析直接使用模拟数据
List<Map<String, String>> studentDataList = new ArrayList<>();
// 模拟数据示例
Map<String, String> student1 = new HashMap<>();
student1.put("studentNumber", "2024001");
student1.put("realName", "张三");
studentDataList.add(student1);
Map<String, String> student2 = new HashMap<>();
student2.put("studentNumber", "2024002");
student2.put("realName", "李四");
studentDataList.add(student2);
// 3. 处理学生数据
int successCount = 0;
int failCount = 0;
List<String> errorMessages = new ArrayList<>();
List<String> createdStudentIds = new ArrayList<>();
for (Map<String, String> studentData : studentDataList) {
try {
String studentNumber = studentData.get("studentNumber");
String realName = studentData.get("realName");
// 检查学生是否已存在
SysUser existingStudent = sysUserService.getUserByName(studentNumber);
String studentId;
if (existingStudent != null) {
// 学生已存在直接使用现有学生ID
studentId = existingStudent.getId();
log.info("学生已存在,使用现有学生: 学号={}, 姓名={}", studentNumber, realName);
} else {
// 学生不存在创建新学生
SysUser newStudent = sysUserService.createStudentUser(studentNumber, realName, null);
studentId = newStudent.getId();
createdStudentIds.add(studentId);
log.info("创建新学生: 学号={}, 姓名={}, ID={}", studentNumber, realName, studentId);
}
// 检查学生是否已在班级中
QueryWrapper<AiolClassStudent> checkWrapper = new QueryWrapper<>();
checkWrapper.eq("class_id", classId)
.eq("student_id", studentId);
AiolClassStudent existingRelation = aiolClassStudentService.getOne(checkWrapper);
if (existingRelation != null) {
log.info("学生已在班级中: 学号={}, 班级ID={}", studentNumber, classId);
continue; // 跳过已存在的学生
}
// 创建班级学生关联
AiolClassStudent classStudent = new AiolClassStudent();
classStudent.setClassId(classId);
classStudent.setStudentId(studentId);
classStudent.setCreateBy(sysUser.getUsername());
classStudent.setCreateTime(new Date());
boolean saved = aiolClassStudentService.save(classStudent);
if (saved) {
successCount++;
log.info("成功将学生添加到班级: 学号={}, 班级ID={}", studentNumber, classId);
} else {
failCount++;
errorMessages.add("保存学生 " + studentNumber + " 到班级失败");
}
} catch (Exception e) {
failCount++;
String errorMsg = "处理学生 " + studentData.get("studentNumber") + " 失败: " + e.getMessage();
errorMessages.add(errorMsg);
log.error(errorMsg, e);
}
}
// 4. 构建返回结果
Map<String, Object> result = new HashMap<>();
result.put("totalCount", studentDataList.size());
result.put("successCount", successCount);
result.put("failCount", failCount);
result.put("createdStudentCount", createdStudentIds.size());
result.put("errorMessages", errorMessages);
result.put("createdStudentIds", createdStudentIds);
log.info("导入学生完成: 班级ID={}, 总数={}, 成功={}, 失败={}, 新创建学生={}",
classId, studentDataList.size(), successCount, failCount, createdStudentIds.size());
return Result.OK(result);
} catch (Exception e) {
log.error("导入学生到班级失败: classId={}, error={}", classId, e.getMessage(), e);
return Result.error("导入学生失败: " + e.getMessage());
}
}
}

View File

@ -317,6 +317,15 @@ public interface ISysUserService extends IService<SysUser> {
*/
void editUser(SysUser user, String roles, String departs, String relTenantIds, String updateFromPage);
/**
* 创建学生用户
* @param studentNumber 学号
* @param realName 真实姓名
* @param password 密码可选默认123456
* @return 创建的用户信息
*/
SysUser createStudentUser(String studentNumber, String realName, String password);
/**
* userId转为username
* @param userIdList

View File

@ -322,6 +322,48 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public SysUser createStudentUser(String studentNumber, String realName, String password) {
// 检查学号是否已存在
SysUser existingUser = this.getUserByName(studentNumber);
if (existingUser != null) {
throw new RuntimeException("学号已存在: " + studentNumber);
}
// 创建学生用户
SysUser studentUser = new SysUser();
studentUser.setUsername(studentNumber); // 学号作为用户名
studentUser.setRealname(realName); // 真实姓名
studentUser.setAvatar("http://103.40.14.23:25528/aiol/manager.jpg"); // 默认头像
studentUser.setSex(1); // 默认性别为1
studentUser.setEmail(null); // 邮箱默认为null
studentUser.setPhone(null); // 手机号默认为null
studentUser.setStatus(1); // 状态为正常
studentUser.setDelFlag(CommonConstant.DEL_FLAG_0); // 未删除
studentUser.setCreateTime(new Date()); // 创建时间
studentUser.setOrgCode(null); // 组织编码为null
// 设置密码
if (oConvertUtils.isEmpty(password)) {
password = "123456"; // 默认密码
}
String salt = oConvertUtils.randomGen(8);
studentUser.setSalt(salt);
String passwordEncode = PasswordUtil.encrypt(studentNumber, password, salt);
studentUser.setPassword(passwordEncode);
// 保存用户
this.save(studentUser);
// 分配学生角色
String studentRoleId = "1955367267343724546"; // 学生角色ID
SysUserRole userRole = new SysUserRole(studentUser.getId(), studentRoleId);
sysUserRoleMapper.insert(userRole);
return studentUser;
}
@Override
@CacheEvict(value= {CacheConstant.SYS_USERS_CACHE}, allEntries=true)
@Transactional(rollbackFor = Exception.class)

View File

@ -33,7 +33,7 @@ public class JeecgSystemApplication extends SpringBootServletInitializer {
app.setDefaultProperties(defaultProperties);
log.info("[JEECG] Elasticsearch Health Check Enabled: false" );
ConfigurableApplicationContext application = app.run(args);;
ConfigurableApplicationContext application = app.run(args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");