From 8fd2aabbba6128700bff656066a9046889ea60a7 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Wed, 14 Oct 2026 14:37:41 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AD=A6=E7=94=9F/=E6=95=99=E5=B8=88?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=88=86=E9=A1=B5=E9=94=99=E4=BD=8D=E4=B8=8E?= =?UTF-8?q?=E7=8F=AD=E7=BA=A7=E9=99=A2=E7=B3=BBtotal=E4=B8=A2=E5=A4=B1?= =?UTF-8?q?=EF=BC=9B=E7=99=BB=E5=BD=95=E5=AF=86=E7=A0=81=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=B8=8E=E8=B4=A6=E5=8F=B7=E4=B8=8D=E5=AD=98=E5=9C=A8=E5=88=86?= =?UTF-8?q?=E5=BC=80=E6=8F=90=E7=A4=BA=EF=BC=9BAI=E5=8A=A9=E8=AF=84?= =?UTF-8?q?=E8=AF=84=E9=A1=B9=E5=90=8D=E5=BD=92=E4=B8=80=E5=8C=96=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E8=AF=AF=E6=8A=A5502?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/stu/LoginController.java | 4 +++ .../controller/stu/UserController.java | 6 +++-- .../impl/AiTrainingEvaluationServiceImpl.java | 17 +++++++++--- .../service/impl/SchoolServiceImpl.java | 26 ++++++++++++++++--- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/stu/LoginController.java b/src/main/java/com/sztzjy/linkCommerce/controller/stu/LoginController.java index 8cd7079..9d53ec3 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/LoginController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/LoginController.java @@ -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, "账号不存在"); } diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java b/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java index c60ffae..ff98385 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java @@ -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 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 userInfoList = userinfoMapper.selectByExample(userInfoExample); for (int i = 0; i < userInfoList.size(); i++) { if (StringUtils.isNotBlank(schoolId)) { diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/AiTrainingEvaluationServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/AiTrainingEvaluationServiceImpl.java index 382665e..c743bb9 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/impl/AiTrainingEvaluationServiceImpl.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/AiTrainingEvaluationServiceImpl.java @@ -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(); } diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolServiceImpl.java index b1a99d3..0be78b0 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolServiceImpl.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolServiceImpl.java @@ -74,6 +74,10 @@ public class SchoolServiceImpl implements SchoolService { } List schoolFaculties = schoolFacultyMapper.selectByExample(schoolFacultyExample); + // 基于分页查询结果读取真实总数/页数,映射出的 DTO 列表最后再替换进去; + // 直接包装 DTO 列表会把 total 错算成当页条数 + PageInfo sourcePage = new PageInfo<>(schoolFaculties); + // 将院系信息转换为 DTO List dtoList = schoolFaculties.stream() .map(schoolFaculty -> { @@ -86,8 +90,13 @@ public class SchoolServiceImpl implements SchoolService { }) .collect(Collectors.toList()); - // 创建 PageInfo 对象,将 DTO 列表封装成分页结果 - return new PageInfo<>(dtoList); + PageInfo 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 schoolClasses = schoolClassMapper.selectByExample(schoolClassExample); + // 基于分页查询结果读取真实总数/页数,映射出的 DTO 列表最后再替换进去; + // 直接包装 DTO 列表会把 total 错算成当页条数 + PageInfo sourcePage = new PageInfo<>(schoolClasses); + // 将院系信息转换为 DTO String schoolName = schoolMapper.selectSchoolNameById(schoolId); List schoolMajorIds = schoolClasses.stream() @@ -201,8 +214,13 @@ public class SchoolServiceImpl implements SchoolService { }) .collect(Collectors.toList()); - // 创建 PageInfo 对象,将 DTO 列表封装成分页结果 - return new PageInfo<>(dtoList); + PageInfo 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