接口编写
2025/5/19大约 9 分钟
用户注册功能
controller层
@Operation(summary = "用户注册")
@PostMapping("/login/register")
public Result register(@RequestBody RegisterDTO registerDTO) {
return userService.regisrer(registerDTO);
}
Service层
@Override
public Result regisrer(RegisterDTO registerDTO) {
boolean register = emailUtils.checkCode(registerDTO.getEmail(), registerDTO.getCode());
if (!register) {
return Result.error("验证码错误");
}
String email = registerDTO.getEmail();
String username = registerDTO.getUsername();
boolean existsEmail = lambdaQuery().eq(User::getEmail, email).exists();
if (existsEmail) {
return Result.error("该邮箱已被注册");
}
boolean existsUsername = lambdaQuery().eq(User::getUsername, username).exists();
if (existsUsername) {
return Result.error("该用户名已被注册");
}
User user = User.builder()
.email(registerDTO.getEmail())
.username(registerDTO.getUsername())
.password(DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes()))
.createTime(LocalDateTime.now())
.updateTime(LocalDateTime.now())
.status(1)
.build();
userMapper.insert(user);
return Result.success();
}
用户修改密码功能
controller层
@Operation(summary = "用户修改密码")
@PostMapping("/login/forget")
public Result forget(@RequestBody ForgetDTO forgetDTO){
return userService.forget(forgetDTO);
}
Service层
@Override
public Result forget(ForgetDTO forgetDTO) {
User user = lambdaQuery().eq(User::getUsername, forgetDTO.getUsername()).one();
if (!user.getEmail().equals(forgetDTO.getEmail())) {
return Result.error("与注册时使用的邮箱不同");
}
boolean register = emailUtils.checkCode(user.getEmail(), forgetDTO.getCode());
if (!register) {
return Result.error("验证码错误");
}
lambdaUpdate()
.eq(User::getUsername, forgetDTO.getUsername())
.set(User::getPassword, DigestUtils.md5DigestAsHex(forgetDTO.getPassword().getBytes()))
.update();
return Result.success();
}
home页面各查询功能的实现
为避免每个用户在进入主页时查询的数据相同而浪费服务器性能,所以将这些数据在服务器不繁忙的时候查询并放入redis中,在用户请求时直接向前端发送数据
转换日期格式
原来的日期格式对用户不太友好,所以通过配置消息转换器来改变日期格式,这样就可以省去为每个日期单独配置了:
创建了一个新的MappingJackson2HttpMessageConverter实例,并设置了自定义的ObjectMapper。这个ObjectMapper被配置为禁用WRITE_DATES_AS_TIMESTAMPS特性,这样就不会把日期时间类型序列化成时间戳。同时,为LocalDateTime指定了一个序列化器,它会根据定义的DATE_TIME_FORMAT格式进行序列化。
@Configuration
public class DateTimeFormatConfiguration implements WebMvcConfigurer {
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 创建一个新的MappingJackson2HttpMessageConverter
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// 设置自定义的ObjectMapper
converter.setObjectMapper(new Jackson2ObjectMapperBuilder()
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)))
.build());
// 将新的转换器添加到列表的首位
converters.add(0, converter);
}
}
查询接口的实现
配置每日任务
导入依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency>
开启任务调度:
启动类添加注解 @EnableScheduling
@MapperScan("com.codelong.mapper") @SpringBootApplication @EnableScheduling public class BackendApplication { public static void main(String[] args) { SpringApplication.run(BackendApplication.class, args); } }
存入缓存
导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
在启动类加上缓存注解
@EnableCaching @MapperScan("com.codelong.mapper") @SpringBootApplication @EnableScheduling public class BackendApplication { public static void main(String[] args) { SpringApplication.run(BackendApplication.class, args); } }
在相关方法加入缓存注解,例如:
@Cacheable(cacheNames = "announcementCache") @Operation(tags = "公告查询接口") @PostMapping("/queryAnnouncement") public Result<List<AnnouncementVO>> query(){ List<AnnouncementVO> list = announcementService.queryNew(); return Result.success(list); }
让VO对象是想序列化接口
@Data @Builder public class AnnouncementVO implements Serializable { private Long id; private String title; private String text; private LocalDateTime createTime; @Serial private static final long serialVersionUID = 1L; }
在其他常用方法添加该注解
题目页面各查询功能的实现
分页查询功能的配置
- 在
MybatisConfiguration
类下添加配置项
@Configuration
public class MybatisConfiguration {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
// 初始化核心插件
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
题目查询接口的实现
创建分页查询结果配置类
@Data @NoArgsConstructor public class PageResult<T> implements Serializable { private List<T> list; private Integer total; }
Controller层
@Operation(summary = "题目查询") @PostMapping public Result<PageResult<ProblemQueryVO>> query(@RequestBody ProblemQueryDTO problemQueryDTO){ PageResult<ProblemQueryVO> list = problemService.queryBySearchAndHard(problemQueryDTO); return Result.success(list); }
Service层
@Override public PageResult<ProblemQueryVO> queryBySearchAndHard(ProblemQueryDTO problemQueryDTO) { LambdaQueryWrapper<Problem> wrapper = new LambdaQueryWrapper<>(); wrapper.select(Problem::getId, Problem::getTitle, Problem::getDifficulty, Problem::getSubNumber, Problem::getAcNumber) .eq(Problem::getStatus, ProblemStatusConstant.PROBLEM_NORMAL) .eq(problemQueryDTO.getHard() != null && problemQueryDTO.getHard() != 0, Problem::getDifficulty, problemQueryDTO.getHard()) .like(problemQueryDTO.getSearch() != null, Problem::getTitle, problemQueryDTO.getSearch()) .orderByAsc(Problem::getId); Page<Problem> pageDomain = Page.of(problemQueryDTO.getPageNumber(), problemQueryDTO.getPageSize()); Page<Problem> page = page(pageDomain, wrapper); List<ProblemQueryVO> list = page.getRecords().stream().map(problem -> ProblemQueryVO.builder() .id(problem.getId()) .title(problem.getTitle()) .hard(problem.getDifficulty()) .total(problem.getSubNumber()) .AcRate(problem.getSubNumber() > 0 ? Math.round((problem.getAcNumber() * 1.0) / (problem.getSubNumber() * 1.0) * 100.0) / 100.0 : 0.0).build()) .collect(Collectors.toList()); Integer total = Math.toIntExact(count(wrapper.select(Problem::getId))); PageResult<ProblemQueryVO> result = new PageResult<>(); result.setList(list); result.setTotal(total); return result; }
标签查询接口的实现
Controller层
@RequiredArgsConstructor @RequestMapping("/tag") @RestController @Slf4j @Tag(name = "标签相关接口") public class TagController { private final TagService tagService; @Operation(summary = "标签查询") @PostMapping("query") @Cacheable("TagCache") public Result query(){ List<TagVO> list = tagService.simpleQuery(); return Result.success(list); } }
Service层
@Override public List<TagVO> simpleQuery() { List<Tag> list = lambdaQuery().select(Tag::getId, Tag::getName, Tag::getMore, Tag::getColor) .orderByAsc(Tag::getId) .list(); List<TagVO> collect = list.stream() .map(tag -> TagVO.builder() .id(tag.getId()) .name(tag.getName()) .color(tag.getColor()) .build()) .collect(Collectors.toList()); return collect; }
题目详情页面接口实现
添加题目提交结果常量类
public class JudgeResultConstant { public static final Integer STATUS_NOT_SUBMITTED = -10; public static final Integer STATUS_SUBMITTING = 9; public static final Integer STATUS_PENDING = 6; public static final Integer STATUS_JUDGING = 7; public static final Integer STATUS_COMPILE_ERROR = -2; public static final Integer STATUS_PRESENTATION_ERROR = -3; public static final Integer STATUS__WRONG_ANSWER = -1; public static final Integer STATUS_ACCEPTED = 0; public static final Integer STATUS__CPU_TIME_LIMIT_EXCEEDED = 1; public static final Integer STATUS__REAL_TIME_LIMIT_EXCEEDED = 2; public static final Integer STATUS__MEMORY_LIMIT_EXCEEDED = 3; public static final Integer STATUS__RUNTIME_ERROR = 4; public static final Integer STATUS__SYSTEM_ERROR = 5; public static final Integer STATUS_PARTIAL_ACCEPTED = 8; public static final Integer STATUS_SUBMITTED_FAILED= 10; }
Controller层
@Operation(summary = "题目详情查询") @PostMapping("/detail") public Result<ProblemDetailVO> detail(@RequestBody ProblemDetailDTO problemDetailDTO){ ProblemDetailVO detailVO = problemService.detail(problemDetailDTO); return Result.success(detailVO); }
Service层
@Override public ProblemDetailVO detail(ProblemDetailDTO problemDetailDTO) { Problem problem = lambdaQuery() .eq(Problem::getId, problemDetailDTO.getId()) .eq(Problem::getStatus, ProblemStatusConstant.PROBLEM_NORMAL) .one(); return ProblemDetailVO.builder() .title(problem.getTitle()) .detail(problem.getDetail()) .difficulty(problem.getDifficulty()) .memoryLimit(problem.getMemoryLimit()) .stackLimit(problem.getStackLimit()) .timeLimit(problem.getTimeLimit()) .acNumber(problem.getAcNumber()) .subNumber(problem.getSubNumber()) .build(); }
题单页面接口实现
已做题目查询接口
@Operation(summary = "已做题目查询")
@PostMapping("/isPassed")
public Result<List<Long>> detail(){
List<Long> list = problemService.isPassed();
return Result.success(list);
}
@Override
public List<Long> isPassed() {
Long id = CurrentIdUtils.getCurrentId();
List<Submission> list = submissionService.lambdaQuery().select(Submission::getProblemId)
.eq(Submission::getUserId, id)
.eq(Submission::getJudgeResult, JudgeResultConstant.STATUS_ACCEPTED)
.orderByAsc(Submission::getProblemId)
.list();
return list.stream().map(Submission::getProblemId).distinct().collect(Collectors.toList());
}
题单和题单详情页面接口
@RestController
@RequestMapping
@Slf4j
@RequiredArgsConstructor
@Tag(name = "题单相关接口")
public class ProblemListController {
private final ProblemListService problemListService;
@Operation(summary = "题单查询接口")
@PostMapping("/problemList")
public Result<List<ProblemListQueryVO>> query(@RequestBody ProblemListQueryDTO problemListQueryDTO) {
List<ProblemListQueryVO> problemDetailVO =problemListService.queryAll(problemListQueryDTO);
return Result.success(problemDetailVO);
}
@Operation(summary = "题单详情查询")
@PostMapping("/problemList/detail")
public Result<ProblemListDetailVO> detail(@RequestBody ProblemListDetailDTO problemListDetailDTO){
ProblemListDetailVO problemListDetailVO = problemListService.detail(problemListDetailDTO);
return Result.success(problemListDetailVO);
}
}
@Service
@RequiredArgsConstructor
public class ProblemListServiceImpl extends ServiceImpl<ProblemListMapper, ProblemList>
implements ProblemListService {
private final ProblemService problemService;
private final ProblemListProblemService problemListProblemService;
@Override
public List<ProblemListQueryVO> queryAll(ProblemListQueryDTO problemQueryDTO) {
List<ProblemList> list = lambdaQuery().select(ProblemList::getId, ProblemList::getName, ProblemList::getNumber, ProblemList::getUpdateTime, ProblemList::getPassword)
.eq(ProblemList::getStatus, ProblemListStatusConstant.ProblemList_NORMAL)
.like(problemQueryDTO.getSearch() != null, ProblemList::getName, problemQueryDTO.getSearch())
.list();
List<ProblemListQueryVO> collect = list.stream().map(domain -> ProblemListQueryVO.builder()
.id(domain.getId())
.name(domain.getName())
.number(domain.getNumber())
.updateTime(domain.getUpdateTime())
.isPrivate(domain.getPassword().isEmpty() ? 0 : 1)
.build())
.collect(Collectors.toList());
return collect;
}
@Override
public ProblemListDetailVO detail(ProblemListDetailDTO problemListDetailDTO) {
ProblemList problemList = lambdaQuery()
.select(ProblemList::getName, ProblemList::getMore, ProblemList::getNumber)
.eq(ProblemList::getId, problemListDetailDTO.getId())
.eq(ProblemList::getStatus, ProblemListStatusConstant.ProblemList_NORMAL)
.one();
List<ProblemListProblem> problemIdList = problemListProblemService.lambdaQuery()
.select(ProblemListProblem::getProblemId)
.eq(ProblemListProblem::getProblemListId, problemListDetailDTO.getId())
.list();
List<Long> collect = problemIdList.stream().map(ProblemListProblem::getProblemId).collect(Collectors.toList());
List<ProblemQueryVO> problemQueryVOS = problemService.listByIds(collect)
.stream().map(problem -> ProblemQueryVO.builder()
.id(problem.getId())
.title(problem.getTitle())
.hard(problem.getDifficulty())
.total(problem.getSubNumber())
.AcRate(problem.getSubNumber() > 0 ? Math.round((problem.getAcNumber() * 1.0) / (problem.getSubNumber() * 1.0) * 100.0) / 100.0
: 0.0)
.build())
.collect(Collectors.toList());
return ProblemListDetailVO.builder()
.title(problemList.getName())
.more(problemList.getMore())
.problemNumber(problemList.getNumber())
.list(problemQueryVOS)
.build();
}
}
"我的"页面接口实现
头像上传接口
核心代码:
@Override
public void upload(MultipartFile multipartFile) {
Long id = CurrentIdUtils.getCurrentId();
try {
User user = getById(id);
if(!user.getAvatar().isEmpty()){
obsUtils.delete(user.getAvatar());
}
} catch (Exception e) {
throw new FileDeleteException(MessageConstant.DELETE_FAILED);
}
try {
String path = obsUtils.upload(multipartFile);
User user = User.builder()
.id(id)
.updateTime(LocalDateTime.now())
.avatar(path)
.build();
updateById(user);
} catch (Exception e) {
throw new FileUploadException(MessageConstant.UPLOAD_FAILED);
}
}
在OBSUtils添加删除文件功能:
public void delete(String url) {
//获取华为云Obs参数
String endpoint = huaWeiOBSConfiguration.getEndPoint();
String accessKeyId = huaWeiOBSConfiguration.getAccessKeyId();
String accessKeySecret = huaWeiOBSConfiguration.getSecretAccessKey();
String bucketName = huaWeiOBSConfiguration.getBucketName();
// 获取上传的文件的输入流
try {
// 删除单个对象
ObsClient obsClient = new ObsClient(accessKeyId, accessKeySecret, endpoint);
String fileName = url.split("/")[3];
obsClient.deleteObject(bucketName, fileName);
System.out.println("deleteObject successfully");
} catch (ObsException e) {
throw new FileDeleteException(MessageConstant.DELETE_FAILED);
}
}
用户信息修改接口
核心代码:
@Override
public void change(UserUpdateDTO user) {
User build = User.builder()
.id(CurrentIdUtils.getCurrentId())
.updateTime(LocalDateTime.now())
.name(user.getName())
.nickname(user.getNickname())
.password(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()))
.build();
updateById(build);
}
比赛页面接口
核心代码
private Integer status(LocalDateTime start, LocalDateTime end) {
if (start.isAfter(LocalDateTime.now())) {
return 0;
} else if (end.isBefore(LocalDateTime.now())) {
return 2;
} else {
return 1;
}
}
@Override
public List<ContestQueryVO> select(ContestQueryDTO contestQueryDTO) {
List<Contest> list;
if (contestQueryDTO.getStatus() == -1) {
list = lambdaQuery()
.like(Contest::getName, contestQueryDTO.getSearch())
.orderByDesc(Contest::getCreateTime)
.list();
return list.stream().map(domain -> ContestQueryVO.builder()
.id(domain.getId())
.name(domain.getName())
.type(domain.getType())
.status(status(domain.getStartTime(), domain.getEndTime()))
.endTime((int) Math.ceil(ChronoUnit.HOURS.between(LocalDateTime.now(),domain.getEndTime()) / 24.0))
.build()).collect(Collectors.toList());
}
if (contestQueryDTO.getStatus().equals(ContestConstant.RACE_NOT_START)) {
list = lambdaQuery()
.like(Contest::getName, contestQueryDTO.getSearch())
.ge(Contest::getStartTime, LocalDateTime.now())
.orderByDesc(Contest::getCreateTime)
.list();
return list.stream().map(domain -> ContestQueryVO.builder()
.id(domain.getId())
.name(domain.getName())
.type(domain.getType())
.status(ContestConstant.RACE_NOT_START)
.endTime((int) Math.ceil(ChronoUnit.HOURS.between(domain.getEndTime(), LocalDateTime.now()) / 24.0))
.build()).collect(Collectors.toList());
} else if (contestQueryDTO.getStatus().equals(ContestConstant.RACE_IS_ON)) {
list = lambdaQuery()
.like(Contest::getName, contestQueryDTO.getSearch())
.le(Contest::getStartTime, LocalDateTime.now())
.ge(Contest::getEndTime, LocalDateTime.now())
.orderByDesc(Contest::getCreateTime)
.list();
return list.stream().map(domain -> ContestQueryVO.builder()
.id(domain.getId())
.name(domain.getName())
.type(domain.getType())
.status(ContestConstant.RACE_IS_ON)
.endTime((int) Math.ceil(ChronoUnit.HOURS.between(LocalDateTime.now(),domain.getEndTime()) / 24.0)).build()).collect(Collectors.toList());
} else if (contestQueryDTO.getStatus().equals(ContestConstant.RACE_IS_OVER)) {
list = lambdaQuery()
.like(Contest::getName, contestQueryDTO.getSearch())
.le(Contest::getEndTime, LocalDateTime.now())
.orderByDesc(Contest::getCreateTime)
.list();
return list.stream().map(domain -> ContestQueryVO.builder()
.id(domain.getId())
.name(domain.getName())
.type(domain.getType())
.status(ContestConstant.RACE_IS_OVER)
.endTime((int) Math.ceil(ChronoUnit.HOURS.between(domain.getEndTime(), LocalDateTime.now()) / 24.0))
.build()).collect(Collectors.toList());
}
throw new ProblemListEmptyException(MessageConstant.PROBLEM_LIST_IS_EMPTY);
}
比赛详情接口
比赛详情查询接口
核心代码:
@Override
public ContestDetailVO detail(Long id) {
Contest contest = getById(id);
if(contest.getStartTime().isAfter(LocalDateTime.now())){
throw new ContestNotBeginException(MessageConstant.CONTEST_NOT_BEGIN);
}
List<ContestProblem> problemsIds = contestProblemService.lambdaQuery()
.eq(ContestProblem::getContestId, id)
.list();
List<Long> ids = problemsIds.stream().map(ContestProblem::getProblemId).toList();
List<Problem> problems = problemService.listByIds(ids);
return ContestDetailVO.builder()
.name(contest.getName())
.more(contest.getMore())
.startTime(contest.getStartTime())
.endTime(contest.getEndTime())
.problemList(problems.stream()
.map(problem -> ProblemQueryVO.builder()
.id(problem.getId())
.title(problem.getTitle())
.hard(problem.getDifficulty())
.total(problem.getSubNumber())
.AcRate(problem.getSubNumber() > 0 ? Math.round((problem.getAcNumber() * 1.0) / (problem.getSubNumber() * 1.0) * 100.0) / 100.0
: 0.0)
.build())
.collect(Collectors.toList()))
.build();
}
比赛排名查询接口
因为此接口逻辑较为复杂,使用加入相关注释,核心代码:
@Override
public List<ContestRankVO> rank(ContestRankDTO rankDTO) {
//分页查询数据
//按照竞赛分数排名(竞赛分数取决于通过题目的最高分数之和)
List<ContestRankIdsDTO> rankIds = contestUserMapper.rankByScore(rankDTO.getId(),(rankDTO.getPageNumber() - 1) * rankDTO.getPageSize(), rankDTO.getPageSize());
if(rankIds.isEmpty()){
throw new RankIsEmptyException(MessageConstant.RANK_IS_EMPTY);
}
ArrayList<User> users = new ArrayList<>();
for (ContestRankIdsDTO idsDTO : rankIds) {
users.add(userService.getById(idsDTO.getUserId()));
}
//查询用户昵称,用户头像
List<ContestRankVO> result = users.stream().map(domain -> ContestRankVO.builder()
.nickname(domain.getNickname())
.avatar(domain.getAvatar())
.build())
.toList();
//查询比赛题目id
List<Long> problemIds = contestProblemService.lambdaQuery()
.eq(ContestProblem::getContestId, rankDTO.getId())
.orderByAsc(ContestProblem::getProblemId)
.list()
.stream().map(ContestProblem::getProblemId).toList();
for (int i = 0; i < result.size(); i++) {
//把刚刚查询出来的分数赋值到结果中
result.get(i).setScore(rankIds.get(i).getScore());
//为这个人赋值名次
result.get(i).setRank(i+1);
List<Integer> score = new ArrayList<>();
List<Integer> changeNumber = new ArrayList<>();
for (Long problemId : problemIds) {
List<Integer> scoreList = submissionService.lambdaQuery()
.eq(Submission::getUserId, rankIds.get(i).getUserId())
.eq(Submission::getProblemId, problemId)
.list()
.stream().map(Submission::getJudgeScore).toList();
if (!scoreList.isEmpty()) {
//查询这个用户对每个题目的提交次数
changeNumber.add(scoreList.size());
//查询这个用户对每个题目的最高分数
Integer maxScore = scoreList.stream().max(Comparator.naturalOrder()).get();
score.add(maxScore);
} else {
changeNumber.add(0);
score.add(0);
}
}
result.get(i).setIsPassed(score);
result.get(i).setTryNumber(changeNumber);
//ac数量
long count = score.stream().filter(sc -> sc == 100).count();
result.get(i).setAcNumber((int) count);
}
//提供分数增加接口,在判题之后进行判断(使用独立的判题接口),根据历史提交判断是否添加
return result;
}
提交记录接口
按条件查询列表
@Override
public List<ProblemRecordListVO> getList(ProblemRecordListDTO dto) {
LambdaQueryWrapper<Submission> wrapper = new LambdaQueryWrapper<>();
if (dto.getResultType() == 1) {
wrapper.eq(dto.getProblemId() != null, Submission::getProblemId, dto.getProblemId())
.eq(dto.getResultType() != null, Submission::getJudgeResult, dto.getResultType())
.eq(Submission::getUserId, CurrentIdUtils.getCurrentId())
.orderByDesc(Submission::getCreateTime);
} else if (dto.getResultType() == 0) {
wrapper.eq(dto.getProblemId() != null, Submission::getProblemId, dto.getProblemId())
.in(dto.getResultType() != null, Submission::getJudgeResult, unaccepted)
.eq(Submission::getUserId, CurrentIdUtils.getCurrentId())
.orderByDesc(Submission::getCreateTime);
} else if (dto.getResultType() == 2) {
wrapper.eq(dto.getProblemId() != null, Submission::getProblemId, dto.getProblemId())
.notIn(dto.getResultType() != null, Submission::getJudgeResult, unaccepted, JudgeResultConstant.STATUS_ACCEPTED)
.eq(Submission::getUserId, CurrentIdUtils.getCurrentId())
.orderByDesc(Submission::getCreateTime);
}else {
wrapper.eq(dto.getProblemId() != null, Submission::getProblemId, dto.getProblemId())
.eq(Submission::getUserId, CurrentIdUtils.getCurrentId())
.orderByDesc(Submission::getCreateTime);
}
Page<Submission> pageDomain = Page.of(dto.getPageNumber(), dto.getPageSize());
Page<Submission> page = submissionService.page(pageDomain, wrapper);
return page.getRecords().stream().map(domain -> ProblemRecordListVO.builder()
.subTime(domain.getCreateTime())
.subResult(domain.getJudgeResult())
.score(domain.getJudgeScore())
.problemTitle(getById(domain.getProblemId()).getTitle())
.problemId(domain.getProblemId())
.subResult(subResult(domain.getJudgeResult()))
.submissionId(domain.getId())
.judgeTime(domain.getJudgeTime())
.codeLanguage(domain.getCodeLanguage())
.build()).toList();
}
按ID查询详情
@Override
public ProblemRecordDetailVO detail(Long submissionId) {
Submission submission = submissionService.lambdaQuery().eq(Submission::getId, submissionId).one();
List<SubPoint> list = subPointService.lambdaQuery().eq(SubPoint::getSubmissionId, submission.getProblemId())
.list();
List<Integer> subPointResult = list.stream().map(SubPoint::getJudgeResult).toList();
List<Long> subPointId = list.stream().map(SubPoint::getJudgePointId).toList();
return ProblemRecordDetailVO.builder()
.code(submission.getCode())
.codeLanguage(submission.getCodeLanguage())
.score(submission.getJudgeScore())
.subTime(submission.getCreateTime())
.judgeResult(subResult(submission.getJudgeResult()))
.problemTitle(getById(submission.getProblemId()).getTitle())
.judgeTime(submission.getJudgeTime())
.judgeMemory(submission.getJudgeMemory())
.subPointResult(subPointResult)
.subPointId(subPointId)
.build();
}
提交记录数量查询
@Override
public Long countById() {
return submissionService.lambdaQuery()
.eq(Submission::getUserId, CurrentIdUtils.getCurrentId())
.count();
}