fix: 学生/教师列表分页错位与班级院系total丢失;登录密码错误与账号不存在分开提示;AI助评评项名归一化修复误报502

main
chenyuan 7 hours ago
parent b3a9a50fc8
commit 8fd2aabbba

@ -27,6 +27,7 @@ import com.sztzjy.linkCommerce.util.TzApi;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -94,6 +95,9 @@ public class LoginController {
}
Userinfo user = userinfos.get(0);
return new ResultEntity(HttpStatus.OK, buildLoginResultMap(user, token));
}catch (BadCredentialsException e){
// 账号存在但密码不正确;账号不存在时 loadUserByUsername 会抛下标越界,走下方兜底
return new ResultEntity(HttpStatus.BAD_REQUEST, "密码错误");
}catch (Exception e){
return new ResultEntity(HttpStatus.BAD_REQUEST, "账号不存在");
}

@ -635,7 +635,6 @@ public class UserController {
}
schoolId = operator.getSchoolId();
}
PageHelper.startPage(index, size);
UserinfoExample userInfoExample = new UserinfoExample();
UserinfoExample.Criteria criteria = userInfoExample.createCriteria();
School school = new School();
@ -650,6 +649,8 @@ public class UserController {
criteria.andUsernameEqualTo(userName);
}
criteria.andRoleEqualTo(3);
// startPage 只对紧随其后的第一条查询生效,必须放在学校等辅助查询之后,否则教师主查询不会分页
PageHelper.startPage(index, size);
List<Userinfo> userInfoList = userinfoMapper.selectByExample(userInfoExample);
for (int i = 0; i < userInfoList.size(); i++) {
if (StringUtils.isNotBlank(schoolId)) {
@ -993,7 +994,6 @@ public class UserController {
if (teacherRosterScope) {
schoolId = operator.getSchoolId();
}
PageHelper.startPage(index, size);
UserinfoExample userInfoExample = new UserinfoExample();
UserinfoExample.Criteria criteria = userInfoExample.createCriteria();
School school = new School();
@ -1029,6 +1029,8 @@ public class UserController {
}
}
criteria.andRoleEqualTo(4);
// startPage 只对紧随其后的第一条查询生效,必须放在学校/教学班/花名册等辅助查询之后,否则学生主查询不会分页
PageHelper.startPage(index, size);
List<Userinfo> userInfoList = userinfoMapper.selectByExample(userInfoExample);
for (int i = 0; i < userInfoList.size(); i++) {
if (StringUtils.isNotBlank(schoolId)) {

@ -361,7 +361,7 @@ public class AiTrainingEvaluationServiceImpl implements AiTrainingEvaluationServ
requireText(criterion, "rationale");
Integer max = wholeNumber(criterion.get("maxScore"));
Integer earned = wholeNumber(criterion.get("score"));
if (!expected.name.equals(StringUtils.trimToEmpty(criterion.path("name").asText()))
if (!normalizeCriterionName(expected.name).equals(normalizeCriterionName(criterion.path("name").asText()))
|| max == null || earned == null || max != expected.maxScore || earned < 0 || earned > max) {
throw invalidReport();
}
@ -492,6 +492,16 @@ public class AiTrainingEvaluationServiceImpl implements AiTrainingEvaluationServ
return new ServiceException(HttpStatus.BAD_GATEWAY, "AI returned an invalid evaluation report");
}
/**
* 评项名比对前的归一化:去掉模型从提示词的编号列表里照搬回来的枚举前缀
* (如 "1."、"2、"、"(3)"、"Step 1"、"第2步")和所有空白。
* 没有编号+分隔符前缀的纯名字(如 "26电商2")不会被误删。
*/
private String normalizeCriterionName(String value) {
String name = StringUtils.trimToEmpty(value).replaceAll("\\s+", "");
return name.replaceFirst("^(?:(?i:step)\\d{0,3}[.::、))-]*|[((]?第\\d{1,3}步?[)).、::-]*|[((]?\\d{1,3}[)).、::-]+)", "");
}
private String helpSystemPrompt() {
return "You are a training learning assistant. Return only JSON with overallDiagnosis, strengths, improvementAreas, and recommendedActions. Do not include a score.";
}
@ -514,7 +524,8 @@ public class AiTrainingEvaluationServiceImpl implements AiTrainingEvaluationServ
+ "Determine each criterion score from its evidence first, then sum the scores. Do not choose a target total, default score or invent differences between students. "
+ "Each rationale must identify the actual evidence or omission and explain the awarded points or deduction. "
+ "There are exactly " + criterionPlan.size() + " training steps and their maximum scores sum to 100. "
+ "Return exactly " + criterionPlan.size() + " criteria in this exact order. Each name and maxScore must exactly match this required step plan: "
+ "Return exactly " + criterionPlan.size() + " criteria in this exact order. "
+ "Each criterion's name must be copied verbatim from the quoted name in this required step plan, without adding any numbering or other characters; maxScore must exactly match: "
+ criterionPlanPrompt(criterionPlan) + ". "
+ "score, maxScore, and each criterion score must be JSON integer numbers (not strings). "
+ "Write one complete concise Chinese sentence for each rationale and end it with Chinese punctuation. "
@ -528,7 +539,7 @@ public class AiTrainingEvaluationServiceImpl implements AiTrainingEvaluationServ
for (int index = 0; index < criterionPlan.size(); index++) {
AssessmentCriterionPlan item = criterionPlan.get(index);
if (index > 0) result.append(", ");
result.append(index + 1).append(". ").append(item.name).append(" (max ").append(item.maxScore).append(")");
result.append(index + 1).append(". \"").append(item.name).append("\" (max ").append(item.maxScore).append(")");
}
return result.append("]").toString();
}

@ -74,6 +74,10 @@ public class SchoolServiceImpl implements SchoolService {
}
List<SchoolFaculty> schoolFaculties = schoolFacultyMapper.selectByExample(schoolFacultyExample);
// 基于分页查询结果读取真实总数/页数,映射出的 DTO 列表最后再替换进去;
// 直接包装 DTO 列表会把 total 错算成当页条数
PageInfo<SchoolFaculty> sourcePage = new PageInfo<>(schoolFaculties);
// 将院系信息转换为 DTO
List<SchoolFacultyDto> dtoList = schoolFaculties.stream()
.map(schoolFaculty -> {
@ -86,8 +90,13 @@ public class SchoolServiceImpl implements SchoolService {
})
.collect(Collectors.toList());
// 创建 PageInfo 对象,将 DTO 列表封装成分页结果
return new PageInfo<>(dtoList);
PageInfo<SchoolFacultyDto> pageInfo = new PageInfo<>();
pageInfo.setTotal(sourcePage.getTotal());
pageInfo.setPageNum(sourcePage.getPageNum());
pageInfo.setPageSize(sourcePage.getPageSize());
pageInfo.setPages(sourcePage.getPages());
pageInfo.setList(dtoList);
return pageInfo;
}
@Override
@ -131,6 +140,10 @@ public class SchoolServiceImpl implements SchoolService {
}
List<SchoolClass> schoolClasses = schoolClassMapper.selectByExample(schoolClassExample);
// 基于分页查询结果读取真实总数/页数,映射出的 DTO 列表最后再替换进去;
// 直接包装 DTO 列表会把 total 错算成当页条数
PageInfo<SchoolClass> sourcePage = new PageInfo<>(schoolClasses);
// 将院系信息转换为 DTO
String schoolName = schoolMapper.selectSchoolNameById(schoolId);
List<String> schoolMajorIds = schoolClasses.stream()
@ -201,8 +214,13 @@ public class SchoolServiceImpl implements SchoolService {
})
.collect(Collectors.toList());
// 创建 PageInfo 对象,将 DTO 列表封装成分页结果
return new PageInfo<>(dtoList);
PageInfo<SchoolClassDto> pageInfo = new PageInfo<>();
pageInfo.setTotal(sourcePage.getTotal());
pageInfo.setPageNum(sourcePage.getPageNum());
pageInfo.setPageSize(sourcePage.getPageSize());
pageInfo.setPages(sourcePage.getPages());
pageInfo.setList(dtoList);
return pageInfo;
}
@Override

Loading…
Cancel
Save