添加编辑器文件上传 修改题目数据、排行榜统计方式
This commit is contained in:
parent
86777c86f2
commit
458d3f1a24
|
@ -27,8 +27,9 @@ public class CorsConfig implements WebMvcConfigurer {
|
||||||
// 前端直接通过/public/img/图片名称即可拿到
|
// 前端直接通过/public/img/图片名称即可拿到
|
||||||
@Override
|
@Override
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
registry.addResourceHandler(Constants.File.IMG_API.getPath() + "**") // /api/public/img/**
|
// /api/public/img/** /api/public/file/**
|
||||||
|
registry.addResourceHandler(Constants.File.IMG_API.getPath() + "**",Constants.File.FILE_API.getPath() + "**")
|
||||||
.addResourceLocations("file:" + Constants.File.USER_AVATAR_FOLDER.getPath() + File.separator,
|
.addResourceLocations("file:" + Constants.File.USER_AVATAR_FOLDER.getPath() + File.separator,
|
||||||
"file:" + Constants.File.MARKDOWN_IMG_FOLDER.getPath() + File.separator);
|
"file:" + Constants.File.MARKDOWN_FILE_FOLDER.getPath() + File.separator);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package top.hcode.hoj.controller.admin;
|
package top.hcode.hoj.controller.admin;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
@ -17,8 +18,10 @@ import top.hcode.hoj.pojo.dto.ProblemDto;
|
||||||
import top.hcode.hoj.pojo.entity.*;
|
import top.hcode.hoj.pojo.entity.*;
|
||||||
import top.hcode.hoj.pojo.vo.AnnouncementVo;
|
import top.hcode.hoj.pojo.vo.AnnouncementVo;
|
||||||
import top.hcode.hoj.service.impl.*;
|
import top.hcode.hoj.service.impl.*;
|
||||||
|
import top.hcode.hoj.utils.Constants;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -226,6 +229,7 @@ public class AdminContestController {
|
||||||
problem的id为其他表的外键的表中的对应数据都会被一起删除!
|
problem的id为其他表的外键的表中的对应数据都会被一起删除!
|
||||||
*/
|
*/
|
||||||
if (result) { // 删除成功
|
if (result) { // 删除成功
|
||||||
|
FileUtil.del(Constants.File.TESTCASE_BASE_FOLDER.getPath() + File.separator + "problem_" + pid);
|
||||||
return CommonResult.successResponse(null, "删除成功!");
|
return CommonResult.successResponse(null, "删除成功!");
|
||||||
} else {
|
} else {
|
||||||
return CommonResult.errorResponse("删除失败!", CommonResult.STATUS_FAIL);
|
return CommonResult.errorResponse("删除失败!", CommonResult.STATUS_FAIL);
|
||||||
|
|
|
@ -38,9 +38,6 @@ public class AdminJudgeController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private JudgeServiceImpl judgeService;
|
private JudgeServiceImpl judgeService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountServiceImpl problemCountService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserAcproblemServiceImpl userAcproblemService;
|
private UserAcproblemServiceImpl userAcproblemService;
|
||||||
|
|
||||||
|
@ -73,15 +70,6 @@ public class AdminJudgeController {
|
||||||
// 如果是非比赛题目
|
// 如果是非比赛题目
|
||||||
if (judge.getCid() == 0 && judge.getCpid() == 0) {
|
if (judge.getCid() == 0 && judge.getCpid() == 0) {
|
||||||
// 重判前,需要将该题目对应记录表一并更新
|
// 重判前,需要将该题目对应记录表一并更新
|
||||||
// 更新该题目的提交统计表problem_count
|
|
||||||
String columnName = Constants.Judge.getTableColumnNameByStatus(judge.getStatus()); // 获取要修改的字段名
|
|
||||||
if (columnName != null) {
|
|
||||||
UpdateWrapper<ProblemCount> problemCountUpdateWrapper = new UpdateWrapper<>();
|
|
||||||
// 重判需要减掉之前的判题结果
|
|
||||||
problemCountUpdateWrapper.setSql(columnName + "=" + columnName + "-1,total=total-1")
|
|
||||||
.eq("pid", judge.getPid());
|
|
||||||
problemCountService.update(problemCountUpdateWrapper);
|
|
||||||
}
|
|
||||||
// 如果该题已经是AC通过状态,更新该题目的用户ac做题表 user_acproblem
|
// 如果该题已经是AC通过状态,更新该题目的用户ac做题表 user_acproblem
|
||||||
if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus().intValue()) {
|
if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus().intValue()) {
|
||||||
QueryWrapper<UserAcproblem> userAcproblemQueryWrapper = new QueryWrapper<>();
|
QueryWrapper<UserAcproblem> userAcproblemQueryWrapper = new QueryWrapper<>();
|
||||||
|
|
|
@ -172,7 +172,7 @@ public class AdminProblemController {
|
||||||
if (problemCases != null && problemCases.size() > 0) {
|
if (problemCases != null && problemCases.size() > 0) {
|
||||||
return CommonResult.successResponse(problemCases, "获取该题目的评测样例列表成功!");
|
return CommonResult.successResponse(problemCases, "获取该题目的评测样例列表成功!");
|
||||||
} else {
|
} else {
|
||||||
return CommonResult.errorResponse("获取该题目的评测样例列表失败!可能该题目测试数据是zip上传的!");
|
return CommonResult.successResponse(null,"获取该题目的评测样例列表为空!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -226,7 +226,11 @@ public class FileController {
|
||||||
|
|
||||||
// 遍历读取与检查是否in和out文件一一对应,否则报错
|
// 遍历读取与检查是否in和out文件一一对应,否则报错
|
||||||
for (File tmp : files) {
|
for (File tmp : files) {
|
||||||
String tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf("."));
|
String tmpPreName = null;
|
||||||
|
try {
|
||||||
|
tmpPreName = tmp.getName().substring(0, tmp.getName().lastIndexOf("."));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
if (tmp.getName().endsWith("in")) {
|
if (tmp.getName().endsWith("in")) {
|
||||||
inputData.put(tmpPreName, tmp.getName());
|
inputData.put(tmpPreName, tmp.getName());
|
||||||
} else if (tmp.getName().endsWith("out") || tmp.getName().endsWith("ans")) {
|
} else if (tmp.getName().endsWith("out") || tmp.getName().endsWith("ans")) {
|
||||||
|
@ -577,11 +581,9 @@ public class FileController {
|
||||||
@RequestMapping(value = "/upload-md-img", method = RequestMethod.POST)
|
@RequestMapping(value = "/upload-md-img", method = RequestMethod.POST)
|
||||||
@RequiresAuthentication
|
@RequiresAuthentication
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@Transactional
|
|
||||||
@RequiresRoles(value = {"root", "admin"}, logical = Logical.OR)
|
|
||||||
public CommonResult uploadMDImg(@RequestParam("image") MultipartFile image) {
|
public CommonResult uploadMDImg(@RequestParam("image") MultipartFile image) {
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
return CommonResult.errorResponse("图片为空!");
|
return CommonResult.errorResponse("上传的图片不能为空!");
|
||||||
}
|
}
|
||||||
if (image.getSize() > 1024 * 1024 * 4) {
|
if (image.getSize() > 1024 * 1024 * 4) {
|
||||||
return CommonResult.errorResponse("上传的图片文件大小不能大于4M!");
|
return CommonResult.errorResponse("上传的图片文件大小不能大于4M!");
|
||||||
|
@ -593,13 +595,13 @@ public class FileController {
|
||||||
}
|
}
|
||||||
|
|
||||||
//若不存在该目录,则创建目录
|
//若不存在该目录,则创建目录
|
||||||
FileUtil.mkdir(Constants.File.MARKDOWN_IMG_FOLDER.getPath());
|
FileUtil.mkdir(Constants.File.MARKDOWN_FILE_FOLDER.getPath());
|
||||||
|
|
||||||
//通过UUID生成唯一文件名
|
//通过UUID生成唯一文件名
|
||||||
String filename = IdUtil.simpleUUID() + "." + suffix;
|
String filename = IdUtil.simpleUUID() + "." + suffix;
|
||||||
try {
|
try {
|
||||||
//将文件保存指定目录
|
//将文件保存指定目录
|
||||||
image.transferTo(FileUtil.file(Constants.File.MARKDOWN_IMG_FOLDER.getPath() + File.separator + filename));
|
image.transferTo(FileUtil.file(Constants.File.MARKDOWN_FILE_FOLDER.getPath() + File.separator + filename));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("图片文件上传异常-------------->{}", e.getMessage());
|
log.error("图片文件上传异常-------------->{}", e.getMessage());
|
||||||
return CommonResult.errorResponse("服务器异常:图片文件上传失败!", CommonResult.STATUS_ERROR);
|
return CommonResult.errorResponse("服务器异常:图片文件上传失败!", CommonResult.STATUS_ERROR);
|
||||||
|
@ -607,17 +609,53 @@ public class FileController {
|
||||||
|
|
||||||
return CommonResult.successResponse(MapUtil.builder()
|
return CommonResult.successResponse(MapUtil.builder()
|
||||||
.put("link", Constants.File.IMG_API.getPath() + filename)
|
.put("link", Constants.File.IMG_API.getPath() + filename)
|
||||||
.put("filePath", Constants.File.MARKDOWN_IMG_FOLDER.getPath() + File.separator + filename).map(),
|
.put("filePath", Constants.File.MARKDOWN_FILE_FOLDER.getPath() + File.separator + filename).map(),
|
||||||
"上传图片成功!");
|
"上传图片成功!");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@RequestMapping(value = "/upload-md-file", method = RequestMethod.POST)
|
||||||
|
@RequiresAuthentication
|
||||||
|
@ResponseBody
|
||||||
|
@RequiresRoles(value = {"root", "admin"}, logical = Logical.OR)
|
||||||
|
public CommonResult uploadMd(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
|
||||||
|
if (file == null) {
|
||||||
|
return CommonResult.errorResponse("上传的文件不能为空!");
|
||||||
|
}
|
||||||
|
if (file.getSize() >= 1024 * 1024 * 128) {
|
||||||
|
return CommonResult.errorResponse("上传的文件大小不能大于128M!");
|
||||||
|
}
|
||||||
|
//获取文件后缀
|
||||||
|
String suffix = "";
|
||||||
|
String filename = "";
|
||||||
|
if (file.getOriginalFilename() != null && file.getOriginalFilename().contains(".")) {
|
||||||
|
suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
|
||||||
|
//通过UUID生成唯一文件名
|
||||||
|
filename = IdUtil.simpleUUID() + "." + suffix;
|
||||||
|
} else {
|
||||||
|
filename = IdUtil.simpleUUID();
|
||||||
|
}
|
||||||
|
//若不存在该目录,则创建目录
|
||||||
|
FileUtil.mkdir(Constants.File.MARKDOWN_FILE_FOLDER.getPath());
|
||||||
|
|
||||||
|
try {
|
||||||
|
//将文件保存指定目录
|
||||||
|
file.transferTo(FileUtil.file(Constants.File.MARKDOWN_FILE_FOLDER.getPath() + File.separator + filename));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("文件上传异常-------------->{}", e.getMessage());
|
||||||
|
return CommonResult.errorResponse("服务器异常:文件上传失败!", CommonResult.STATUS_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonResult.successResponse(MapUtil.builder()
|
||||||
|
.put("link", Constants.File.FILE_API.getPath() + filename).map(),
|
||||||
|
"上传文件成功!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@RequestMapping(value = "/delete-md-img", method = RequestMethod.GET)
|
@RequestMapping(value = "/delete-md-img", method = RequestMethod.GET)
|
||||||
@RequiresAuthentication
|
@RequiresAuthentication
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@Transactional
|
|
||||||
@RequiresRoles(value = {"root", "admin"}, logical = Logical.OR)
|
|
||||||
public CommonResult uploadMDImg(@RequestParam("filePath") String filePath) {
|
public CommonResult uploadMDImg(@RequestParam("filePath") String filePath) {
|
||||||
boolean result = FileUtil.del(filePath);
|
boolean result = FileUtil.del(filePath);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -928,6 +966,7 @@ public class FileController {
|
||||||
qdojProblemDto.setIsSpj(spj != null);
|
qdojProblemDto.setIsSpj(spj != null);
|
||||||
Problem problem = new Problem();
|
Problem problem = new Problem();
|
||||||
problem.setAuth(1)
|
problem.setAuth(1)
|
||||||
|
.setIsUploadCase(true)
|
||||||
.setSource(problemJson.getStr("source", null))
|
.setSource(problemJson.getStr("source", null))
|
||||||
.setDifficulty(1)
|
.setDifficulty(1)
|
||||||
.setProblemId(problemJson.getStr("display_id"))
|
.setProblemId(problemJson.getStr("display_id"))
|
||||||
|
|
|
@ -60,8 +60,6 @@ public class ContestController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProblemLanguageServiceImpl problemLanguageService;
|
private ProblemLanguageServiceImpl problemLanguageService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountServiceImpl problemCountService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JudgeServiceImpl judgeService;
|
private JudgeServiceImpl judgeService;
|
||||||
|
@ -298,7 +296,7 @@ public class ContestController {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取题目的提交记录
|
// 获取题目的提交记录
|
||||||
ProblemCount problemCount = problemCountService.getContestProblemCount(contestProblem.getPid(), contestProblem.getId(), contestProblem.getCid());
|
ProblemCountVo problemCount = judgeService.getContestProblemCount(contestProblem.getPid(), contestProblem.getId(), contestProblem.getCid());
|
||||||
|
|
||||||
// 获取题目的代码模板
|
// 获取题目的代码模板
|
||||||
QueryWrapper<CodeTemplate> codeTemplateQueryWrapper = new QueryWrapper<>();
|
QueryWrapper<CodeTemplate> codeTemplateQueryWrapper = new QueryWrapper<>();
|
||||||
|
|
|
@ -59,9 +59,6 @@ public class JudgeController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProblemService problemService;
|
private ProblemService problemService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UserRecordServiceImpl userRecordService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ContestProblemServiceImpl contestProblemService;
|
private ContestProblemServiceImpl contestProblemService;
|
||||||
|
|
||||||
|
@ -71,9 +68,6 @@ public class JudgeController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ContestRecordServiceImpl contestRecordService;
|
private ContestRecordServiceImpl contestRecordService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountServiceImpl problemCountService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserAcproblemServiceImpl userAcproblemService;
|
private UserAcproblemServiceImpl userAcproblemService;
|
||||||
|
|
||||||
|
@ -116,8 +110,6 @@ public class JudgeController {
|
||||||
.setSubmitTime(new Date())
|
.setSubmitTime(new Date())
|
||||||
.setVersion(0)
|
.setVersion(0)
|
||||||
.setIp(IpUtils.getUserIpAddr(request));
|
.setIp(IpUtils.getUserIpAddr(request));
|
||||||
|
|
||||||
boolean updateUserRecord = true;
|
|
||||||
boolean updateContestRecord = true;
|
boolean updateContestRecord = true;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
// 如果比赛id不等于0,则说明为比赛提交,需要查询对应的contest_problem的主键
|
// 如果比赛id不等于0,则说明为比赛提交,需要查询对应的contest_problem的主键
|
||||||
|
@ -197,15 +189,11 @@ public class JudgeController {
|
||||||
Problem problem = problemService.getOne(problemQueryWrapper);
|
Problem problem = problemService.getOne(problemQueryWrapper);
|
||||||
judge.setCpid(0L).setPid(problem.getId()).setDisplayPid(problem.getProblemId());
|
judge.setCpid(0L).setPid(problem.getId()).setDisplayPid(problem.getProblemId());
|
||||||
|
|
||||||
// 更新一下user_record表
|
|
||||||
UpdateWrapper<UserRecord> userRecordUpdateWrapper = new UpdateWrapper<>();
|
|
||||||
userRecordUpdateWrapper.setSql("submissions=submissions+1").eq("uid", judge.getUid());
|
|
||||||
updateUserRecord = userRecordService.update(userRecordUpdateWrapper);
|
|
||||||
// 将新提交数据插入数据库
|
// 将新提交数据插入数据库
|
||||||
result = judgeMapper.insert(judge);
|
result = judgeMapper.insert(judge);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != 1 || !updateContestRecord || !updateUserRecord) {
|
if (result != 1 || !updateContestRecord) {
|
||||||
return CommonResult.errorResponse("代码提交失败!", CommonResult.STATUS_ERROR);
|
return CommonResult.errorResponse("代码提交失败!", CommonResult.STATUS_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,15 +236,6 @@ public class JudgeController {
|
||||||
// 如果是非比赛题目
|
// 如果是非比赛题目
|
||||||
if (judge.getCid() == 0) {
|
if (judge.getCid() == 0) {
|
||||||
// 重判前,需要将该题目对应记录表一并更新
|
// 重判前,需要将该题目对应记录表一并更新
|
||||||
// 更新该题目的提交统计表problem_count
|
|
||||||
String columnName = Constants.Judge.getTableColumnNameByStatus(judge.getStatus()); // 获取要修改的字段名
|
|
||||||
if (columnName != null) {
|
|
||||||
UpdateWrapper<ProblemCount> problemCountUpdateWrapper = new UpdateWrapper<>();
|
|
||||||
// 重判需要减掉之前的判题结果
|
|
||||||
problemCountUpdateWrapper.setSql(columnName + "=" + columnName + "-1,total=total-1")
|
|
||||||
.eq("pid", judge.getPid());
|
|
||||||
problemCountService.update(problemCountUpdateWrapper);
|
|
||||||
}
|
|
||||||
// 如果该题已经是AC通过状态,更新该题目的用户ac做题表 user_acproblem
|
// 如果该题已经是AC通过状态,更新该题目的用户ac做题表 user_acproblem
|
||||||
if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus().intValue()) {
|
if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus().intValue()) {
|
||||||
QueryWrapper<UserAcproblem> userAcproblemQueryWrapper = new QueryWrapper<>();
|
QueryWrapper<UserAcproblem> userAcproblemQueryWrapper = new QueryWrapper<>();
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.*;
|
||||||
import top.hcode.hoj.common.result.CommonResult;
|
import top.hcode.hoj.common.result.CommonResult;
|
||||||
import top.hcode.hoj.pojo.dto.PidListDto;
|
import top.hcode.hoj.pojo.dto.PidListDto;
|
||||||
import top.hcode.hoj.pojo.entity.*;
|
import top.hcode.hoj.pojo.entity.*;
|
||||||
|
import top.hcode.hoj.pojo.vo.ProblemCountVo;
|
||||||
import top.hcode.hoj.pojo.vo.ProblemInfoVo;
|
import top.hcode.hoj.pojo.vo.ProblemInfoVo;
|
||||||
import top.hcode.hoj.pojo.vo.ProblemVo;
|
import top.hcode.hoj.pojo.vo.ProblemVo;
|
||||||
import top.hcode.hoj.pojo.vo.UserRolesVo;
|
import top.hcode.hoj.pojo.vo.UserRolesVo;
|
||||||
|
@ -54,8 +55,6 @@ public class ProblemController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProblemLanguageServiceImpl problemLanguageService;
|
private ProblemLanguageServiceImpl problemLanguageService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountServiceImpl problemCountService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private CodeTemplateServiceImpl codeTemplateService;
|
private CodeTemplateServiceImpl codeTemplateService;
|
||||||
|
@ -255,9 +254,7 @@ public class ProblemController {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取题目的提交记录
|
// 获取题目的提交记录
|
||||||
QueryWrapper<ProblemCount> problemCountQueryWrapper = new QueryWrapper<>();
|
ProblemCountVo problemCount = judgeService.getProblemCount(problem.getId());
|
||||||
problemCountQueryWrapper.eq("pid", problem.getId());
|
|
||||||
ProblemCount problemCount = problemCountService.getOne(problemCountQueryWrapper);
|
|
||||||
|
|
||||||
// 获取题目的代码模板
|
// 获取题目的代码模板
|
||||||
QueryWrapper<CodeTemplate> codeTemplateQueryWrapper = new QueryWrapper<>();
|
QueryWrapper<CodeTemplate> codeTemplateQueryWrapper = new QueryWrapper<>();
|
||||||
|
|
|
@ -8,8 +8,8 @@ import org.springframework.stereotype.Repository;
|
||||||
import top.hcode.hoj.pojo.entity.Judge;
|
import top.hcode.hoj.pojo.entity.Judge;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import top.hcode.hoj.pojo.vo.JudgeVo;
|
import top.hcode.hoj.pojo.vo.JudgeVo;
|
||||||
|
import top.hcode.hoj.pojo.vo.ProblemCountVo;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -29,4 +29,8 @@ public interface JudgeMapper extends BaseMapper<Judge> {
|
||||||
@Param("username") String username, @Param("uid") String uid, @Param("beforeContestSubmit") Boolean beforeContestSubmit);
|
@Param("username") String username, @Param("uid") String uid, @Param("beforeContestSubmit") Boolean beforeContestSubmit);
|
||||||
|
|
||||||
int getTodayJudgeNum();
|
int getTodayJudgeNum();
|
||||||
|
|
||||||
|
ProblemCountVo getContestProblemCount(@Param("pid") Long pid, @Param("cpid") Long cpid, @Param("cid") Long cid);
|
||||||
|
|
||||||
|
ProblemCountVo getProblemCount(@Param("pid") Long pid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package top.hcode.hoj.dao;
|
|
||||||
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
import top.hcode.hoj.pojo.entity.ProblemCount;
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Mapper 接口
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Himit_ZH
|
|
||||||
* @since 2020-10-23
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
@Repository
|
|
||||||
public interface ProblemCountMapper extends BaseMapper<ProblemCount> {
|
|
||||||
ProblemCount getContestProblemCount(@Param("pid") Long pid, @Param("cpid") Long cpid, @Param("cid") Long cid);
|
|
||||||
}
|
|
|
@ -2,8 +2,9 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="top.hcode.hoj.dao.AnnouncementMapper">
|
<mapper namespace="top.hcode.hoj.dao.AnnouncementMapper">
|
||||||
|
|
||||||
<select id="getAnnouncementList" resultMap="map_AnnouncementVo">
|
<select id="getAnnouncementList" resultMap="map_AnnouncementVo" useCache="true">
|
||||||
SELECT a.*,u.username FROM user_info u,announcement a where a.uid = u.uuid
|
SELECT a.*,u.username FROM user_info u,announcement a where a.uid = u.uuid
|
||||||
|
and (SELECT COUNT(*) FROM contest_announcement ca WHERE ca.aid=a.id) = 0
|
||||||
<if test="notAdmin">
|
<if test="notAdmin">
|
||||||
and a.status = 0
|
and a.status = 0
|
||||||
</if>
|
</if>
|
||||||
|
|
|
@ -62,4 +62,32 @@
|
||||||
<select id="getTodayJudgeNum" resultType="int">
|
<select id="getTodayJudgeNum" resultType="int">
|
||||||
SELECT count(*) FROM judge WHERE DATE(gmt_create) = CURDATE();
|
SELECT count(*) FROM judge WHERE DATE(gmt_create) = CURDATE();
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getContestProblemCount" resultType="top.hcode.hoj.pojo.vo.ProblemCountVo">
|
||||||
|
SELECT COUNT(IF(status=-3,status,NULL)) AS pe,
|
||||||
|
COUNT(IF(status=-2,status,NULL)) AS ce,
|
||||||
|
COUNT(IF(status=-1,status,NULL)) AS wa,
|
||||||
|
COUNT(IF(status=0,status,NULL)) AS ac,
|
||||||
|
COUNT(IF(status=1,status,NULL)) AS tle,
|
||||||
|
COUNT(IF(status=2,status,NULL)) AS mle,
|
||||||
|
COUNT(IF(status=3,status,NULL)) AS re,
|
||||||
|
COUNT(IF(status=4,status,NULL)) AS se,
|
||||||
|
COUNT(IF(status=8,status,NULL)) AS pa,
|
||||||
|
COUNT(*) AS total
|
||||||
|
FROM judge where pid=#{pid} and cpid = #{cpid} and cid = #{cid}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="getProblemCount" resultType="top.hcode.hoj.pojo.vo.ProblemCountVo">
|
||||||
|
SELECT COUNT(IF(status=-3,status,NULL)) AS pe,
|
||||||
|
COUNT(IF(status=-2,status,NULL)) AS ce,
|
||||||
|
COUNT(IF(status=-1,status,NULL)) AS wa,
|
||||||
|
COUNT(IF(status=0,status,NULL)) AS ac,
|
||||||
|
COUNT(IF(status=1,status,NULL)) AS tle,
|
||||||
|
COUNT(IF(status=2,status,NULL)) AS mle,
|
||||||
|
COUNT(IF(status=3,status,NULL)) AS re,
|
||||||
|
COUNT(IF(status=4,status,NULL)) AS se,
|
||||||
|
COUNT(IF(status=8,status,NULL)) AS pa,
|
||||||
|
COUNT(*) AS total
|
||||||
|
FROM judge where pid=#{pid}
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
<?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="top.hcode.hoj.dao.ProblemCountMapper">
|
|
||||||
<select id="getContestProblemCount" resultType="top.hcode.hoj.pojo.entity.ProblemCount">
|
|
||||||
SELECT COUNT(IF(status=-3,status,NULL)) AS pe,
|
|
||||||
COUNT(IF(status=-2,status,NULL)) AS ce,
|
|
||||||
COUNT(IF(status=-1,status,NULL)) AS wa,
|
|
||||||
COUNT(IF(status=0,status,NULL)) AS ac,
|
|
||||||
COUNT(IF(status=1,status,NULL)) AS tle,
|
|
||||||
COUNT(IF(status=2,status,NULL)) AS mle,
|
|
||||||
COUNT(IF(status=3,status,NULL)) AS re,
|
|
||||||
COUNT(IF(status=4,status,NULL)) AS se,
|
|
||||||
COUNT(IF(status=8,status,NULL)) AS pa,
|
|
||||||
COUNT(*) AS total
|
|
||||||
FROM judge where pid=#{pid} and cpid = #{cpid} and cid = #{cid}
|
|
||||||
</select>
|
|
||||||
</mapper>
|
|
|
@ -24,9 +24,35 @@
|
||||||
|
|
||||||
<!-- 主查询 -->
|
<!-- 主查询 -->
|
||||||
<select id="getProblemList" resultMap="map_ProblemList">
|
<select id="getProblemList" resultMap="map_ProblemList">
|
||||||
SELECT distinct p.id as pid,p.problem_id,p.title,p.difficulty,p.type,pc.total,pc.ac,pc.mle,pc.tle,pc.re,
|
SELECT DISTINCT p.id AS pid, p.problem_id, p.title, p.difficulty, p.type
|
||||||
pc.pe,pc.ce,pc.wa,pc.se,pc.pa FROM problem p
|
, COALESCE(j.pe, 0) AS pe
|
||||||
LEFT JOIN problem_count pc ON p.id = pc.pid
|
, COALESCE(j.ce, 0) AS ce
|
||||||
|
, COALESCE(j.wa, 0) AS wa
|
||||||
|
, COALESCE(j.ac, 0) AS ac
|
||||||
|
, COALESCE(j.tle, 0) AS tle
|
||||||
|
, COALESCE(j.mle, 0) AS mle
|
||||||
|
, COALESCE(j.re, 0) AS re
|
||||||
|
, COALESCE(j.se, 0) AS se
|
||||||
|
, COALESCE(j.pa, 0) AS pa
|
||||||
|
, COALESCE(j.total, 0) AS total
|
||||||
|
FROM problem p
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT j.pid AS pid
|
||||||
|
, COUNT(IF(j.status = -3, STATUS, NULL)) AS pe
|
||||||
|
, COUNT(IF(j.status = -2, STATUS, NULL)) AS ce
|
||||||
|
, COUNT(IF(j.status = -1, STATUS, NULL)) AS wa
|
||||||
|
, COUNT(IF(j.status = 0, STATUS, NULL)) AS ac
|
||||||
|
, COUNT(IF(j.status = 1, STATUS, NULL)) AS tle
|
||||||
|
, COUNT(IF(j.status = 2, STATUS, NULL)) AS mle
|
||||||
|
, COUNT(IF(j.status = 3, STATUS, NULL)) AS re
|
||||||
|
, COUNT(IF(j.status = 4, STATUS, NULL)) AS se
|
||||||
|
, COUNT(IF(j.status = 8, STATUS, NULL)) AS pa
|
||||||
|
, COUNT(*) AS total
|
||||||
|
FROM judge j
|
||||||
|
WHERE j.pid
|
||||||
|
GROUP BY j.pid
|
||||||
|
) j
|
||||||
|
ON j.pid = p.id
|
||||||
LEFT JOIN problem_tag pt ON p.id = pt.pid
|
LEFT JOIN problem_tag pt ON p.id = pt.pid
|
||||||
<where>
|
<where>
|
||||||
p.auth = 1
|
p.auth = 1
|
||||||
|
|
|
@ -2,37 +2,39 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="top.hcode.hoj.dao.UserRecordMapper">
|
<mapper namespace="top.hcode.hoj.dao.UserRecordMapper">
|
||||||
<select id="getACMRankList" resultType="top.hcode.hoj.pojo.vo.ACMRankVo" useCache="true">
|
<select id="getACMRankList" resultType="top.hcode.hoj.pojo.vo.ACMRankVo" useCache="true">
|
||||||
SELECT u.uuid as uid,u.nickname,u.username,u.signature,u.avatar,ur.submissions as total,ur.rating,
|
SELECT u.uuid as uid,u.nickname,u.username,u.signature,u.avatar,
|
||||||
(SELECT COUNT( DISTINCT pid ) FROM user_acproblem WHERE uid =u.uuid) AS solved,
|
(SELECT COUNT( DISTINCT pid ) FROM user_acproblem WHERE uid =u.uuid) AS solved,
|
||||||
(SELECT COUNT(pid) FROM user_acproblem WHERE uid =u.uuid) AS ac
|
(SELECT COUNT(pid) FROM user_acproblem WHERE uid =u.uuid) AS ac,
|
||||||
FROM user_info u,user_record ur WHERE u.uuid = ur.uid AND u.status = 0
|
(SELECT COUNT(uid) FROM judge WHERE uid=u.uuid) AS total
|
||||||
|
FROM user_info u WHERE u.status = 0
|
||||||
ORDER BY solved DESC,ac DESC
|
ORDER BY solved DESC,ac DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getRecent7ACRank" resultType="top.hcode.hoj.pojo.vo.ACMRankVo">
|
<select id="getRecent7ACRank" resultType="top.hcode.hoj.pojo.vo.ACMRankVo">
|
||||||
SELECT u.uuid as uid,u.nickname,u.username,u.signature,u.avatar,ur.submissions as total,ur.rating,
|
SELECT u.uuid as uid,u.nickname,u.username,u.signature,u.avatar,
|
||||||
|
|
||||||
(SELECT COUNT( DISTINCT pid ) FROM user_acproblem WHERE uid =u.uuid
|
(SELECT COUNT( DISTINCT pid ) FROM user_acproblem WHERE uid =u.uuid
|
||||||
and DATE(gmt_create) >= DATE_SUB(CURDATE(),INTERVAL 7 DAY) ) AS solved,
|
and DATE(gmt_create) >= DATE_SUB(CURDATE(),INTERVAL 7 DAY) ) AS solved,
|
||||||
|
(SELECT COUNT(pid) FROM user_acproblem WHERE uid =u.uuid
|
||||||
(SELECT COUNT(pid) FROM user_acproblem WHERE uid =u.uuid
|
and DATE(gmt_create) >= DATE_SUB(CURDATE(),INTERVAL 7 DAY)) AS ac,
|
||||||
and DATE(gmt_create) >= DATE_SUB(CURDATE(),INTERVAL 7 DAY)) AS ac
|
(SELECT COUNT(uid) FROM judge WHERE uid=u.uuid) AS total
|
||||||
|
FROM user_info u WHERE u.status = 0
|
||||||
FROM user_info u,user_record ur WHERE u.uuid = ur.uid AND u.status = 0
|
ORDER BY solved DESC,ac DESC LIMIT 10
|
||||||
ORDER BY solved DESC,ac DESC LIMIT 10
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getOIRankList" resultType="top.hcode.hoj.pojo.vo.OIRankVo" useCache="true">
|
<select id="getOIRankList" resultType="top.hcode.hoj.pojo.vo.OIRankVo" useCache="true">
|
||||||
SELECT u.uuid as uid,u.nickname,u.username,u.signature,u.avatar,ur.submissions as total,ur.rating,
|
SELECT u.uuid as uid,u.nickname,u.username,u.signature,u.avatar,
|
||||||
ur.total_score as score,
|
(SELECT IFNULL(SUM(score),0) FROM judge WHERE uid=u.uuid) AS score,
|
||||||
(SELECT COUNT(pid) FROM user_acproblem WHERE uid =u.uuid) AS ac
|
(SELECT COUNT(pid) FROM user_acproblem WHERE uid =u.uuid) AS ac,
|
||||||
FROM user_info u,user_record ur WHERE u.uuid = ur.uid AND u.status = 0
|
(SELECT COUNT(uid) FROM judge WHERE uid=u.uuid) AS total
|
||||||
ORDER BY score DESC,ac DESC
|
FROM user_info u WHERE u.status = 0
|
||||||
|
ORDER BY score DESC,ac DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getUserHomeInfo" resultType="top.hcode.hoj.pojo.vo.UserHomeVo">
|
<select id="getUserHomeInfo" resultType="top.hcode.hoj.pojo.vo.UserHomeVo">
|
||||||
SELECT u.username,u.signature,u.school,u.github,u.blog,u.avatar,ur.submissions as total,ur.rating,
|
SELECT u.username,u.signature,u.school,u.github,u.blog,u.avatar,ur.rating,
|
||||||
ur.total_score as score
|
(SELECT IFNULL(SUM(score),0) FROM judge WHERE uid=u.uuid) AS score,
|
||||||
|
(SELECT COUNT(uid) FROM judge WHERE uid=u.uuid) AS total
|
||||||
FROM user_info u,user_record ur WHERE u.uuid = ur.uid AND u.status = 0 AND u.uuid = #{uid}
|
FROM user_info u,user_record ur WHERE u.uuid = ur.uid AND u.status = 0 AND u.uuid = #{uid}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package top.hcode.hoj.pojo.entity;
|
package top.hcode.hoj.pojo.vo;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
|
@ -19,16 +19,11 @@ import java.util.Date;
|
||||||
* @since 2020-10-23
|
* @since 2020-10-23
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = false)
|
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@ApiModel(value="ProblemCount对象", description="")
|
public class ProblemCountVo implements Serializable {
|
||||||
public class ProblemCount implements Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@TableId(value = "pid", type = IdType.ID_WORKER)
|
|
||||||
private Long pid;
|
|
||||||
|
|
||||||
private Integer total;
|
private Integer total;
|
||||||
|
|
||||||
private Integer ac;
|
private Integer ac;
|
||||||
|
@ -57,14 +52,4 @@ public class ProblemCount implements Serializable {
|
||||||
@ApiModelProperty(value = "部分通过,OI题目")
|
@ApiModelProperty(value = "部分通过,OI题目")
|
||||||
private Integer pa;
|
private Integer pa;
|
||||||
|
|
||||||
@Version
|
|
||||||
private Long version;
|
|
||||||
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
|
||||||
private Date gmtCreate;
|
|
||||||
|
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
|
||||||
private Date gmtModified;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,7 +3,6 @@ package top.hcode.hoj.pojo.vo;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import top.hcode.hoj.pojo.entity.Problem;
|
import top.hcode.hoj.pojo.entity.Problem;
|
||||||
import top.hcode.hoj.pojo.entity.ProblemCount;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -19,6 +18,6 @@ public class ProblemInfoVo {
|
||||||
private Problem problem;
|
private Problem problem;
|
||||||
private List<String> tags;
|
private List<String> tags;
|
||||||
private List<String> languages;
|
private List<String> languages;
|
||||||
private ProblemCount problemCount;
|
private ProblemCountVo problemCount;
|
||||||
private HashMap<String, String> codeTemplate;
|
private HashMap<String, String> codeTemplate;
|
||||||
}
|
}
|
|
@ -2,16 +2,11 @@ package top.hcode.hoj.service;
|
||||||
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import top.hcode.hoj.pojo.entity.Judge;
|
import top.hcode.hoj.pojo.entity.Judge;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import top.hcode.hoj.pojo.entity.ToJudge;
|
|
||||||
import top.hcode.hoj.pojo.vo.JudgeVo;
|
import top.hcode.hoj.pojo.vo.JudgeVo;
|
||||||
|
import top.hcode.hoj.pojo.vo.ProblemCountVo;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,4 +28,7 @@ public interface JudgeService extends IService<Judge> {
|
||||||
|
|
||||||
void failToUseRedisPublishJudge(Long submitId, Long pid, Boolean isContest);
|
void failToUseRedisPublishJudge(Long submitId, Long pid, Boolean isContest);
|
||||||
|
|
||||||
|
ProblemCountVo getContestProblemCount(Long pid, Long cpid, Long cid);
|
||||||
|
|
||||||
|
ProblemCountVo getProblemCount(Long pid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package top.hcode.hoj.service;
|
|
||||||
|
|
||||||
import top.hcode.hoj.pojo.entity.ProblemCount;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 服务类
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Himit_ZH
|
|
||||||
* @since 2020-10-23
|
|
||||||
*/
|
|
||||||
public interface ProblemCountService extends IService<ProblemCount> {
|
|
||||||
ProblemCount getContestProblemCount(Long pid, Long cpid, Long cid);
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
package top.hcode.hoj.service.impl;
|
package top.hcode.hoj.service.impl;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
@ -8,8 +7,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import top.hcode.hoj.pojo.entity.ContestRecord;
|
import top.hcode.hoj.pojo.entity.ContestRecord;
|
||||||
import top.hcode.hoj.pojo.entity.Judge;
|
import top.hcode.hoj.pojo.entity.Judge;
|
||||||
import top.hcode.hoj.dao.JudgeMapper;
|
import top.hcode.hoj.dao.JudgeMapper;
|
||||||
import top.hcode.hoj.pojo.entity.ProblemCount;
|
|
||||||
import top.hcode.hoj.pojo.vo.JudgeVo;
|
import top.hcode.hoj.pojo.vo.JudgeVo;
|
||||||
|
import top.hcode.hoj.pojo.vo.ProblemCountVo;
|
||||||
import top.hcode.hoj.service.JudgeService;
|
import top.hcode.hoj.service.JudgeService;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -30,9 +29,6 @@ public class JudgeServiceImpl extends ServiceImpl<JudgeMapper, Judge> implements
|
||||||
@Autowired
|
@Autowired
|
||||||
private JudgeMapper judgeMapper;
|
private JudgeMapper judgeMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountServiceImpl problemCountService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ContestRecordServiceImpl contestRecordService;
|
private ContestRecordServiceImpl contestRecordService;
|
||||||
|
|
||||||
|
@ -61,15 +57,8 @@ public class JudgeServiceImpl extends ServiceImpl<JudgeMapper, Judge> implements
|
||||||
.set("error_message", "The something has gone wrong with the data Backup server. Please report this to administrator.")
|
.set("error_message", "The something has gone wrong with the data Backup server. Please report this to administrator.")
|
||||||
.set("status", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
|
.set("status", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
|
||||||
judgeMapper.update(null, judgeUpdateWrapper);
|
judgeMapper.update(null, judgeUpdateWrapper);
|
||||||
// 更新problem_count 表
|
// 更新contest_record表
|
||||||
if (!isContest) {
|
if (isContest) {
|
||||||
QueryWrapper<ProblemCount> problemCountQueryWrapper = new QueryWrapper<ProblemCount>();
|
|
||||||
problemCountQueryWrapper.eq("pid", pid);
|
|
||||||
ProblemCount problemCount = problemCountService.getOne(problemCountQueryWrapper);
|
|
||||||
problemCount.setSe(problemCount.getSe() + 1);
|
|
||||||
problemCountService.saveOrUpdate(problemCount);
|
|
||||||
} else {
|
|
||||||
// 更新contest_record表
|
|
||||||
UpdateWrapper<ContestRecord> updateWrapper = new UpdateWrapper<>();
|
UpdateWrapper<ContestRecord> updateWrapper = new UpdateWrapper<>();
|
||||||
updateWrapper.eq("submit_id", submitId) // submit_id一定只有一个
|
updateWrapper.eq("submit_id", submitId) // submit_id一定只有一个
|
||||||
.set("first_blood", false)
|
.set("first_blood", false)
|
||||||
|
@ -78,4 +67,14 @@ public class JudgeServiceImpl extends ServiceImpl<JudgeMapper, Judge> implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProblemCountVo getContestProblemCount(Long pid, Long cpid, Long cid) {
|
||||||
|
return judgeMapper.getContestProblemCount(pid, cpid, cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProblemCountVo getProblemCount(Long pid) {
|
||||||
|
return judgeMapper.getProblemCount(pid);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
package top.hcode.hoj.service.impl;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import top.hcode.hoj.pojo.entity.ProblemCount;
|
|
||||||
import top.hcode.hoj.dao.ProblemCountMapper;
|
|
||||||
import top.hcode.hoj.service.ProblemCountService;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 服务实现类
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Himit_ZH
|
|
||||||
* @since 2020-10-23
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class ProblemCountServiceImpl extends ServiceImpl<ProblemCountMapper, ProblemCount> implements ProblemCountService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountMapper problemCountMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProblemCount getContestProblemCount(Long pid, Long cpid, Long cid) {
|
|
||||||
return problemCountMapper.getContestProblemCount(pid,cpid, cid);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,6 +17,7 @@ import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.DigestUtils;
|
import org.springframework.util.DigestUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
import top.hcode.hoj.crawler.problem.CFProblemStrategy;
|
import top.hcode.hoj.crawler.problem.CFProblemStrategy;
|
||||||
import top.hcode.hoj.crawler.problem.HDUProblemStrategy;
|
import top.hcode.hoj.crawler.problem.HDUProblemStrategy;
|
||||||
|
@ -70,9 +71,6 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProblemTagServiceImpl problemTagService;
|
private ProblemTagServiceImpl problemTagService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountServiceImpl problemCountService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ApplicationContext applicationContext;
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@ -236,87 +234,68 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
|
|
||||||
boolean checkProblemCase = true;
|
boolean checkProblemCase = true;
|
||||||
|
|
||||||
if (!problem.getIsRemote()) { // 如果是自家的题目才有测试数据
|
if (!problem.getIsRemote() && problemDto.getSamples().size() > 0) { // 如果是自家的题目才有测试数据
|
||||||
// 如果是选择上传测试文件的,则需要遍历对应文件夹,读取数据,写入数据库,先前的题目数据一并清空。
|
int sumScore = 0;
|
||||||
if (problemDto.getIsUploadTestCase()) {
|
// 新增加的case列表
|
||||||
// 如果是选择了上传测试文件的模式,但是数据为空,那就是修改题目,但是没修改测试数据,需要判断
|
List<ProblemCase> newProblemCaseList = new LinkedList<>();
|
||||||
if (problemDto.getSamples().size() > 0) {
|
// 需要修改的case列表
|
||||||
int sumScore = 0;
|
List<ProblemCase> needUpdateProblemCaseList = new LinkedList<>();
|
||||||
String testcaseDir = problemDto.getUploadTestcaseDir();
|
// 遍历上传的case列表,如果还存在,则从需要删除的测试样例列表移除该id
|
||||||
|
for (ProblemCase problemCase : problemDto.getSamples()) {
|
||||||
|
if (problemCase.getId() != null) { // 已存在的case
|
||||||
|
needDeleteProblemCases.remove(problemCase.getId());
|
||||||
|
// 跟原先的数据做对比,如果变动 则加入需要修改的case列表
|
||||||
|
ProblemCase oldProblemCase = oldProblemMap.get(problemCase.getId());
|
||||||
|
if (!oldProblemCase.getInput().equals(problemCase.getInput()) ||
|
||||||
|
!oldProblemCase.getOutput().equals(problemCase.getOutput())) {
|
||||||
|
needUpdateProblemCaseList.add(problemCase);
|
||||||
|
} else if (problem.getType().intValue() == Constants.Contest.TYPE_OI.getCode()) {
|
||||||
|
if (oldProblemCase.getScore().intValue() != problemCase.getScore()) {
|
||||||
|
needUpdateProblemCaseList.add(problemCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newProblemCaseList.add(problemCase);
|
||||||
|
}
|
||||||
|
if (problemCase.getScore() != null) {
|
||||||
|
sumScore += problemCase.getScore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 设置oi总分数,根据每个测试点的加和
|
||||||
|
if (problem.getType().intValue() == Constants.Contest.TYPE_OI.getCode()) {
|
||||||
|
problem.setIoScore(sumScore);
|
||||||
|
}
|
||||||
|
// 执行批量删除操作
|
||||||
|
boolean deleteCasesFromProblemResult = true;
|
||||||
|
if (needDeleteProblemCases.size() > 0) {
|
||||||
|
deleteCasesFromProblemResult = problemCaseService.removeByIds(needDeleteProblemCases);
|
||||||
|
}
|
||||||
|
// 执行批量添加操作
|
||||||
|
boolean addCasesToProblemResult = true;
|
||||||
|
if (newProblemCaseList.size() > 0) {
|
||||||
|
addCasesToProblemResult = problemCaseService.saveBatch(newProblemCaseList);
|
||||||
|
}
|
||||||
|
// 执行批量修改操作
|
||||||
|
boolean updateCasesToProblemResult = true;
|
||||||
|
if (needUpdateProblemCaseList.size() > 0) {
|
||||||
|
updateCasesToProblemResult = problemCaseService.saveOrUpdateBatch(needUpdateProblemCaseList);
|
||||||
|
}
|
||||||
|
checkProblemCase = addCasesToProblemResult && deleteCasesFromProblemResult && updateCasesToProblemResult;
|
||||||
|
|
||||||
|
// 只要有新添加,修改,删除都需要更新版本号 同时更新测试数据
|
||||||
|
String caseVersion = String.valueOf(System.currentTimeMillis());
|
||||||
|
if (needDeleteProblemCases.size() > 0 || newProblemCaseList.size() > 0 || needUpdateProblemCaseList.size() > 0) {
|
||||||
|
problem.setCaseVersion(caseVersion);
|
||||||
|
// 如果是选择上传测试文件的,临时文件路径不为空,则需要遍历对应文件夹,读取数据,写入数据库,先前的题目数据一并清空。
|
||||||
|
String testcaseDir = problemDto.getUploadTestcaseDir();
|
||||||
|
if (problemDto.getIsUploadTestCase() && !StringUtils.isEmpty(testcaseDir)) {
|
||||||
// 将之前的临时文件夹里面的评测文件全部复制到指定文件夹(覆盖)
|
// 将之前的临时文件夹里面的评测文件全部复制到指定文件夹(覆盖)
|
||||||
FileUtil.copyFilesFromDir(new File(testcaseDir), new File(Constants.File.TESTCASE_BASE_FOLDER.getPath() + File.separator + "problem_" + pid), true);
|
FileUtil.copyFilesFromDir(new File(testcaseDir), new File(Constants.File.TESTCASE_BASE_FOLDER.getPath() + File.separator + "problem_" + pid), true);
|
||||||
// 如果是io题目统计总分
|
|
||||||
for (ProblemCase problemCase : problemDto.getSamples()) {
|
|
||||||
if (problemCase.getScore() != null) {
|
|
||||||
sumScore += problemCase.getScore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 设置oi总分数,根据每个测试点的加和
|
|
||||||
if (problem.getType().intValue() == Constants.Contest.TYPE_OI.getCode()) {
|
|
||||||
problem.setIoScore(sumScore);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置新的测试样例版本号
|
|
||||||
String caseVersion = String.valueOf(System.currentTimeMillis());
|
|
||||||
problem.setCaseVersion(caseVersion);
|
|
||||||
// 获取代理bean对象执行异步方法===》根据测试文件初始info
|
// 获取代理bean对象执行异步方法===》根据测试文件初始info
|
||||||
applicationContext.getBean(ProblemServiceImpl.class).initUploadTestCase(problem.getSpjLanguage() != null, caseVersion, pid, problemDto.getSamples());
|
applicationContext.getBean(ProblemServiceImpl.class).initUploadTestCase(problem.getSpjLanguage() != null, caseVersion, pid, problemDto.getSamples());
|
||||||
|
}else{
|
||||||
|
applicationContext.getBean(ProblemServiceImpl.class).initHandTestCase(problem.getSpjLanguage() != null, problem.getCaseVersion(), pid, problemDto.getSamples());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (problemDto.getSamples().size() > 0) {
|
|
||||||
int sumScore = 0;
|
|
||||||
// 新增加的case列表
|
|
||||||
List<ProblemCase> newProblemCaseList = new LinkedList<>();
|
|
||||||
// 需要修改的case列表
|
|
||||||
List<ProblemCase> needUpdateProblemCaseList = new LinkedList<>();
|
|
||||||
// 遍历上传的case列表,如果还存在,则从需要删除的测试样例列表移除该id
|
|
||||||
for (ProblemCase problemCase : problemDto.getSamples()) {
|
|
||||||
if (problemCase.getId() != null) { // 已存在的case
|
|
||||||
needDeleteProblemCases.remove(problemCase.getId());
|
|
||||||
// 跟原先的数据做对比,如果变动 则加入需要修改的case列表
|
|
||||||
ProblemCase oldProblemCase = oldProblemMap.get(problemCase.getId());
|
|
||||||
if (!oldProblemCase.getInput().equals(problemCase.getInput()) ||
|
|
||||||
!oldProblemCase.getOutput().equals(problemCase.getOutput())) {
|
|
||||||
needUpdateProblemCaseList.add(problemCase);
|
|
||||||
} else if (problem.getType().intValue() == Constants.Contest.TYPE_OI.getCode()) {
|
|
||||||
if (oldProblemCase.getScore().intValue() != problemCase.getScore()) {
|
|
||||||
needUpdateProblemCaseList.add(problemCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newProblemCaseList.add(problemCase);
|
|
||||||
}
|
|
||||||
if (problemCase.getScore() != null) {
|
|
||||||
sumScore += problemCase.getScore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 设置oi总分数,根据每个测试点的加和
|
|
||||||
if (problem.getType().intValue() == Constants.Contest.TYPE_OI.getCode()) {
|
|
||||||
problem.setIoScore(sumScore);
|
|
||||||
}
|
|
||||||
// 执行批量删除操作
|
|
||||||
boolean deleteCasesFromProblemResult = true;
|
|
||||||
if (needDeleteProblemCases.size() > 0) {
|
|
||||||
deleteCasesFromProblemResult = problemCaseService.removeByIds(needDeleteProblemCases);
|
|
||||||
}
|
|
||||||
// 执行批量添加操作
|
|
||||||
boolean addCasesToProblemResult = true;
|
|
||||||
if (newProblemCaseList.size() > 0) {
|
|
||||||
addCasesToProblemResult = problemCaseService.saveBatch(newProblemCaseList);
|
|
||||||
}
|
|
||||||
// 执行批量修改操作
|
|
||||||
boolean updateCasesToProblemResult = true;
|
|
||||||
if (needUpdateProblemCaseList.size() > 0) {
|
|
||||||
updateCasesToProblemResult = problemCaseService.saveOrUpdateBatch(needUpdateProblemCaseList);
|
|
||||||
}
|
|
||||||
checkProblemCase = addCasesToProblemResult && deleteCasesFromProblemResult && updateCasesToProblemResult;
|
|
||||||
|
|
||||||
// 只要有新添加,修改,删除都需要更新版本号 同时更新测试数据
|
|
||||||
if (needDeleteProblemCases.size() > 0 || newProblemCaseList.size() > 0 || needUpdateProblemCaseList.size() > 0) {
|
|
||||||
problem.setCaseVersion(String.valueOf(System.currentTimeMillis()));
|
|
||||||
initHandTestCase(problem.getSpjLanguage() != null, problem.getCaseVersion(), pid, problemDto.getSamples());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +312,7 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -375,15 +355,18 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
// 将之前的临时文件夹里面的评测文件全部复制到指定文件夹(覆盖)
|
// 将之前的临时文件夹里面的评测文件全部复制到指定文件夹(覆盖)
|
||||||
FileUtil.copyFilesFromDir(new File(testcaseDir), new File(Constants.File.TESTCASE_BASE_FOLDER.getPath() + File.separator + "problem_" + pid), true);
|
FileUtil.copyFilesFromDir(new File(testcaseDir), new File(Constants.File.TESTCASE_BASE_FOLDER.getPath() + File.separator + "problem_" + pid), true);
|
||||||
// 如果是io题目统计总分
|
// 如果是io题目统计总分
|
||||||
for (ProblemCase problemCase : problemDto.getSamples()) {
|
List<ProblemCase> problemCases = problemDto.getSamples();
|
||||||
|
for (ProblemCase problemCase : problemCases) {
|
||||||
if (problemCase.getScore() != null) {
|
if (problemCase.getScore() != null) {
|
||||||
sumScore += problemCase.getScore();
|
sumScore += problemCase.getScore();
|
||||||
}
|
}
|
||||||
|
problemCase.setPid(pid);
|
||||||
}
|
}
|
||||||
// 设置oi总分数,根据每个测试点的加和
|
// 设置oi总分数,根据每个测试点的加和
|
||||||
if (problem.getType().intValue() == Constants.Contest.TYPE_OI.getCode()) {
|
if (problem.getType().intValue() == Constants.Contest.TYPE_OI.getCode()) {
|
||||||
problem.setIoScore(sumScore);
|
problem.setIoScore(sumScore);
|
||||||
}
|
}
|
||||||
|
addCasesToProblemResult = problemCaseService.saveOrUpdateBatch(problemCases);
|
||||||
// 获取代理bean对象执行异步方法===》根据测试文件初始info
|
// 获取代理bean对象执行异步方法===》根据测试文件初始info
|
||||||
applicationContext.getBean(ProblemServiceImpl.class).initUploadTestCase(problem.getSpjLanguage() != null, problem.getCaseVersion(), pid, problemDto.getSamples());
|
applicationContext.getBean(ProblemServiceImpl.class).initUploadTestCase(problem.getSpjLanguage() != null, problem.getCaseVersion(), pid, problemDto.getSamples());
|
||||||
} else {
|
} else {
|
||||||
|
@ -414,12 +397,9 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
}
|
}
|
||||||
boolean addTagsToProblemResult = problemTagService.saveOrUpdateBatch(problemTagList);
|
boolean addTagsToProblemResult = problemTagService.saveOrUpdateBatch(problemTagList);
|
||||||
|
|
||||||
// 为新的题目初始化problem_count表
|
|
||||||
boolean initProblemCountResult = problemCountService.save(new ProblemCount().setPid(pid));
|
|
||||||
|
|
||||||
|
|
||||||
if (addProblemResult && addCasesToProblemResult && addLangToProblemResult
|
if (addProblemResult && addCasesToProblemResult && addLangToProblemResult
|
||||||
&& addTagsToProblemResult && initProblemCountResult && addProblemCodeTemplate) {
|
&& addTagsToProblemResult && addProblemCodeTemplate) {
|
||||||
// 修改数据库成功后,如果有进行文件上传操作,则进行删除
|
// 修改数据库成功后,如果有进行文件上传操作,则进行删除
|
||||||
if (problemDto.getIsUploadTestCase()) {
|
if (problemDto.getIsUploadTestCase()) {
|
||||||
FileUtil.del(problemDto.getUploadTestcaseDir());
|
FileUtil.del(problemDto.getUploadTestcaseDir());
|
||||||
|
@ -454,7 +434,7 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
jsonObject.set("outputName", problemCase.getOutput());
|
jsonObject.set("outputName", problemCase.getOutput());
|
||||||
// 读取输出文件
|
// 读取输出文件
|
||||||
FileReader readFile = new FileReader(testCasesDir + "/" + problemCase.getOutput(), CharsetUtil.UTF_8);
|
FileReader readFile = new FileReader(testCasesDir + "/" + problemCase.getOutput(), CharsetUtil.UTF_8);
|
||||||
String output = readFile.readString().replaceAll("\r\n","\n");
|
String output = readFile.readString().replaceAll("\r\n", "\n");
|
||||||
|
|
||||||
// spj是根据特判程序输出判断结果,所以无需初始化测试数据
|
// spj是根据特判程序输出判断结果,所以无需初始化测试数据
|
||||||
if (!isSpj) {
|
if (!isSpj) {
|
||||||
|
@ -478,6 +458,7 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
|
|
||||||
|
|
||||||
// 初始化手动输入上传的测试数据,写成json文件
|
// 初始化手动输入上传的测试数据,写成json文件
|
||||||
|
@Async
|
||||||
public void initHandTestCase(Boolean isSpj,
|
public void initHandTestCase(Boolean isSpj,
|
||||||
String version,
|
String version,
|
||||||
Long problemId,
|
Long problemId,
|
||||||
|
@ -505,7 +486,7 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
String outputName = (index + 1) + ".out";
|
String outputName = (index + 1) + ".out";
|
||||||
jsonObject.set("outputName", outputName);
|
jsonObject.set("outputName", outputName);
|
||||||
// 生成对应文件
|
// 生成对应文件
|
||||||
String outputData = problemCaseList.get(index).getOutput().replaceAll("\r\n","\n");
|
String outputData = problemCaseList.get(index).getOutput().replaceAll("\r\n", "\n");
|
||||||
FileWriter outFile = new FileWriter(testCasesDir + "/" + outputName, CharsetUtil.UTF_8);
|
FileWriter outFile = new FileWriter(testCasesDir + "/" + outputName, CharsetUtil.UTF_8);
|
||||||
outFile.write(outputData);
|
outFile.write(outputData);
|
||||||
|
|
||||||
|
@ -571,9 +552,6 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
boolean addProblemLanguageResult = problemLanguageService.saveOrUpdateBatch(problemLanguageList);
|
boolean addProblemLanguageResult = problemLanguageService.saveOrUpdateBatch(problemLanguageList);
|
||||||
|
|
||||||
|
|
||||||
// 为新的题目初始化problem_count表
|
|
||||||
boolean initProblemCountResult = problemCountService.save(new ProblemCount().setPid(problem.getId()));
|
|
||||||
|
|
||||||
boolean addProblemTagResult = true;
|
boolean addProblemTagResult = true;
|
||||||
List<Tag> addTagList = remoteProblemInfo.getTagList();
|
List<Tag> addTagList = remoteProblemInfo.getTagList();
|
||||||
|
|
||||||
|
@ -613,7 +591,7 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
.setPid(problem.getId()));
|
.setPid(problem.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return addProblemResult && addProblemTagResult && addProblemLanguageResult && initProblemCountResult;
|
return addProblemResult && addProblemTagResult && addProblemLanguageResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -626,6 +604,7 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
|
||||||
.setGmtCreate(null)
|
.setGmtCreate(null)
|
||||||
.setId(null)
|
.setId(null)
|
||||||
.setAuth(1)
|
.setAuth(1)
|
||||||
|
.setIsUploadCase(true)
|
||||||
.setAuthor(null)
|
.setAuthor(null)
|
||||||
.setGmtModified(null);
|
.setGmtModified(null);
|
||||||
HashMap<String, Object> problemMap = new HashMap<>();
|
HashMap<String, Object> problemMap = new HashMap<>();
|
||||||
|
|
|
@ -53,15 +53,6 @@ public class Constants {
|
||||||
public String getColumnName() {
|
public String getColumnName() {
|
||||||
return columnName;
|
return columnName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getTableColumnNameByStatus(int status) {
|
|
||||||
for (Judge judge : Judge.values()) {
|
|
||||||
if (judge.getStatus() == status) {
|
|
||||||
return judge.getColumnName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RemoteOJ {
|
public enum RemoteOJ {
|
||||||
|
@ -160,10 +151,12 @@ public class Constants {
|
||||||
|
|
||||||
USER_AVATAR_FOLDER("/hoj/file/avatar"),
|
USER_AVATAR_FOLDER("/hoj/file/avatar"),
|
||||||
|
|
||||||
MARKDOWN_IMG_FOLDER("/hoj/file/md"),
|
MARKDOWN_FILE_FOLDER("/hoj/file/md"),
|
||||||
|
|
||||||
IMG_API("/api/public/img/"),
|
IMG_API("/api/public/img/"),
|
||||||
|
|
||||||
|
FILE_API("/api/public/file/"),
|
||||||
|
|
||||||
TESTCASE_TMP_FOLDER("/hoj/file/zip"),
|
TESTCASE_TMP_FOLDER("/hoj/file/zip"),
|
||||||
|
|
||||||
TESTCASE_BASE_FOLDER("/hoj/testcase"),
|
TESTCASE_BASE_FOLDER("/hoj/testcase"),
|
||||||
|
|
|
@ -15,6 +15,7 @@ spring:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 128MB
|
max-file-size: 128MB
|
||||||
max-request-size: 128MB
|
max-request-size: 128MB
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
host: ${hoj.redis.host:${REDIS_HOST:172.20.0.2}}
|
host: ${hoj.redis.host:${REDIS_HOST:172.20.0.2}}
|
||||||
port: ${hoj.redis.port:${REDIS_PORT:6379}}
|
port: ${hoj.redis.port:${REDIS_PORT:6379}}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
${AnsiColor.BRIGHT_YELLOW}
|
||||||
|
|
||||||
|
,--, ,----..
|
||||||
|
,--.'| ,----.. / / \ ,---, ,---,.
|
||||||
|
,--, | : / / \ / . : .' .' `\ ,' .' |
|
||||||
|
,---.'| : '| : : . / ;. \,---.' \ ,---.' |
|
||||||
|
| | : _' |. | ;. /. ; / ` ;| | .`\ || | .'
|
||||||
|
: : |.' |. ; /--` ; | ; \ ; |: : | ' |: : |-,
|
||||||
|
| ' ' ; :; | ; | : | ; | '| ' ' ; :: | ;/|
|
||||||
|
' | .'. || : | . | ' ' ' :' | ; . || : .'
|
||||||
|
| | : | '. | '___ ' ; \; / || | : | '| | |-,
|
||||||
|
' : | : ;' ; : .'| \ \ ', / ' : | / ; ' : ;/|
|
||||||
|
| | ' ,/ ' | '/ : ; : / | | '` ,/ | | \
|
||||||
|
; : ;--' | : / \ \ .' ; : .' | : .'
|
||||||
|
| ,/ \ \ .' `---` | ,.' | | ,' @Author Himit_ZH
|
||||||
|
'---' `---` '---' `----'
|
|
@ -3,6 +3,9 @@ hoj-backstage:
|
||||||
nacos-url: ${NACOS_URL:172.20.0.4:8848} # nacos的地址
|
nacos-url: ${NACOS_URL:172.20.0.4:8848} # nacos的地址
|
||||||
server:
|
server:
|
||||||
port: ${hoj-backstage.port}
|
port: ${hoj-backstage.port}
|
||||||
|
servlet:
|
||||||
|
encoding:
|
||||||
|
force: true
|
||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: prod
|
active: prod
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class RestTemplateConfig {
|
||||||
@Bean
|
@Bean
|
||||||
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
|
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
|
||||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||||
factory.setReadTimeout(10000);//单位为ms
|
factory.setReadTimeout(90000);//单位为ms
|
||||||
factory.setConnectTimeout(10000);//单位为ms
|
factory.setConnectTimeout(10000);//单位为ms
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package top.hcode.hoj.dao;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
import top.hcode.hoj.pojo.entity.ProblemCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Mapper 接口
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Himit_ZH
|
|
||||||
* @since 2020-10-23
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
@Repository
|
|
||||||
public interface ProblemCountMapper extends BaseMapper<ProblemCount> {
|
|
||||||
|
|
||||||
}
|
|
|
@ -83,7 +83,7 @@ public class SandboxRun {
|
||||||
static {
|
static {
|
||||||
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
|
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
|
||||||
requestFactory.setConnectTimeout(20000);
|
requestFactory.setConnectTimeout(20000);
|
||||||
requestFactory.setReadTimeout(20000);
|
requestFactory.setReadTimeout(180000);
|
||||||
restTemplate = new RestTemplate(requestFactory);
|
restTemplate = new RestTemplate(requestFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package top.hcode.hoj.service;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import top.hcode.hoj.pojo.entity.Judge;
|
|
||||||
import top.hcode.hoj.pojo.entity.ProblemCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 服务类
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Himit_ZH
|
|
||||||
* @since 2020-10-23
|
|
||||||
*/
|
|
||||||
public interface ProblemCountService extends IService<ProblemCount> {
|
|
||||||
|
|
||||||
void updateCount(int status, Long pid);
|
|
||||||
|
|
||||||
}
|
|
|
@ -36,14 +36,9 @@ public class JudgeServiceImpl extends ServiceImpl<JudgeMapper, Judge> implements
|
||||||
@Autowired
|
@Autowired
|
||||||
private JudgeStrategy judgeStrategy;
|
private JudgeStrategy judgeStrategy;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountServiceImpl problemCountService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserAcproblemServiceImpl userAcproblemService;
|
private UserAcproblemServiceImpl userAcproblemService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UserRecordServiceImpl userRecordService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ContestRecordServiceImpl contestRecordService;
|
private ContestRecordServiceImpl contestRecordService;
|
||||||
|
@ -99,14 +94,6 @@ public class JudgeServiceImpl extends ServiceImpl<JudgeMapper, Judge> implements
|
||||||
.setSubmitId(submitId)
|
.setSubmitId(submitId)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// 比赛的提交不纳入,更新该提交对应题目的数据
|
|
||||||
problemCountService.updateCount(status, pid);
|
|
||||||
|
|
||||||
|
|
||||||
// 如果是非比赛提交,且为OI题目的提交,需要判断是否更新用户得分
|
|
||||||
if (score != null) {
|
|
||||||
userRecordService.updateRecord(uid, submitId, pid, score);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { //如果是比赛提交
|
} else { //如果是比赛提交
|
||||||
contestRecordService.UpdateContestRecord(uid, score, status, submitId, cid);
|
contestRecordService.UpdateContestRecord(uid, score, status, submitId, cid);
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
package top.hcode.hoj.service.impl;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Isolation;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import top.hcode.hoj.dao.ProblemCountMapper;
|
|
||||||
import top.hcode.hoj.pojo.entity.Judge;
|
|
||||||
import top.hcode.hoj.pojo.entity.ProblemCount;
|
|
||||||
import top.hcode.hoj.pojo.entity.UserRecord;
|
|
||||||
import top.hcode.hoj.service.ProblemCountService;
|
|
||||||
import top.hcode.hoj.util.Constants;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 服务实现类
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Himit_ZH
|
|
||||||
* @since 2020-10-23
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class ProblemCountServiceImpl extends ServiceImpl<ProblemCountMapper, ProblemCount> implements ProblemCountService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ProblemCountMapper problemCountMapper;
|
|
||||||
|
|
||||||
// 默认的事务隔离等级可重复读会产生幻读,读不到新的version数据,所以需要更换等级为读已提交
|
|
||||||
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
|
|
||||||
@Async
|
|
||||||
public void updateCount(int status, Long pid) {
|
|
||||||
|
|
||||||
// 更新problem_count 表
|
|
||||||
QueryWrapper<ProblemCount> problemCountQueryWrapper = new QueryWrapper<ProblemCount>();
|
|
||||||
problemCountQueryWrapper.eq("pid", pid);
|
|
||||||
ProblemCount problemCount = problemCountMapper.selectOne(problemCountQueryWrapper);
|
|
||||||
ProblemCount newProblemCount = getNewProblemCount(status, problemCount);
|
|
||||||
newProblemCount.setVersion(problemCount.getVersion());
|
|
||||||
int num = problemCountMapper.updateById(newProblemCount);
|
|
||||||
|
|
||||||
|
|
||||||
if (num == 1) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// 进行重试操作
|
|
||||||
tryAgainUpdate(status, pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
|
|
||||||
public boolean tryAgainUpdate(int status, Long pid) {
|
|
||||||
boolean retryable;
|
|
||||||
int attemptNumber = 0;
|
|
||||||
do {
|
|
||||||
// 查询最新版本号
|
|
||||||
QueryWrapper<ProblemCount> problemCountQueryWrapper = new QueryWrapper<ProblemCount>();
|
|
||||||
problemCountQueryWrapper.eq("pid", pid);
|
|
||||||
ProblemCount problemCount = problemCountMapper.selectOne(problemCountQueryWrapper);
|
|
||||||
|
|
||||||
// 更新
|
|
||||||
ProblemCount newProblemCount = getNewProblemCount(status, problemCount);
|
|
||||||
newProblemCount.setVersion(problemCount.getVersion());
|
|
||||||
boolean success = problemCountMapper.updateById(newProblemCount) == 1;
|
|
||||||
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
attemptNumber++;
|
|
||||||
retryable = attemptNumber < 8;
|
|
||||||
if (attemptNumber == 8) {
|
|
||||||
log.error("超过最大重试次数");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Thread.sleep(300);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (retryable);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProblemCount getNewProblemCount(int status, ProblemCount oldProblemCount) {
|
|
||||||
|
|
||||||
ProblemCount newProblemCount = new ProblemCount();
|
|
||||||
newProblemCount.setPid(oldProblemCount.getPid()).setTotal(oldProblemCount.getTotal() + 1);
|
|
||||||
Constants.Judge type = Constants.Judge.getTypeByStatus(status);
|
|
||||||
switch (type) {
|
|
||||||
case STATUS_ACCEPTED:
|
|
||||||
newProblemCount.setAc(oldProblemCount.getAc() + 1);
|
|
||||||
break;
|
|
||||||
case STATUS_MEMORY_LIMIT_EXCEEDED:
|
|
||||||
newProblemCount.setMle(oldProblemCount.getMle() + 1);
|
|
||||||
break;
|
|
||||||
case STATUS_TIME_LIMIT_EXCEEDED:
|
|
||||||
newProblemCount.setTle(oldProblemCount.getTle() + 1);
|
|
||||||
break;
|
|
||||||
case STATUS_RUNTIME_ERROR:
|
|
||||||
newProblemCount.setRe(oldProblemCount.getRe() + 1);
|
|
||||||
break;
|
|
||||||
case STATUS_PRESENTATION_ERROR:
|
|
||||||
newProblemCount.setPe(oldProblemCount.getPe() + 1);
|
|
||||||
break;
|
|
||||||
case STATUS_COMPILE_ERROR:
|
|
||||||
newProblemCount.setCe(oldProblemCount.getCe() + 1);
|
|
||||||
break;
|
|
||||||
case STATUS_WRONG_ANSWER:
|
|
||||||
newProblemCount.setWa(oldProblemCount.getWa() + 1);
|
|
||||||
break;
|
|
||||||
case STATUS_SYSTEM_ERROR:
|
|
||||||
newProblemCount.setSe(oldProblemCount.getSe() + 1);
|
|
||||||
break;
|
|
||||||
case STATUS_PARTIAL_ACCEPTED:
|
|
||||||
newProblemCount.setPa(oldProblemCount.getPa() + 1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return newProblemCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -31,10 +31,17 @@ public class UserRecordServiceImpl extends ServiceImpl<UserRecordMapper, UserRec
|
||||||
@Autowired
|
@Autowired
|
||||||
private JudgeServiceImpl judgeService;
|
private JudgeServiceImpl judgeService;
|
||||||
|
|
||||||
// 默认的事务隔离等级可重复读会产生幻读,读不到新的version数据,所以需要更换等级为读已提交
|
/**
|
||||||
|
* @MethodNameupdateRecord
|
||||||
|
* @Params * @param null
|
||||||
|
* @Description 本方法启用,不适合数据一致性
|
||||||
|
* @Return
|
||||||
|
* @Since 2021/6/2
|
||||||
|
*/
|
||||||
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
|
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
|
||||||
@Async
|
@Async
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public void updateRecord(String uid, Long submitId, Long pid, Integer score) {
|
public void updateRecord(String uid, Long submitId, Long pid, Integer score) {
|
||||||
QueryWrapper<Judge> judgeQueryWrapper = new QueryWrapper<>();
|
QueryWrapper<Judge> judgeQueryWrapper = new QueryWrapper<>();
|
||||||
judgeQueryWrapper.isNotNull("score")
|
judgeQueryWrapper.isNotNull("score")
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
${AnsiColor.BRIGHT_YELLOW}
|
||||||
|
|
||||||
|
,--, ,----..
|
||||||
|
,--.'| ,----.. / / \ ,---, ,---,.
|
||||||
|
,--, | : / / \ / . : .' .' `\ ,' .' |
|
||||||
|
,---.'| : '| : : . / ;. \,---.' \ ,---.' |
|
||||||
|
| | : _' |. | ;. /. ; / ` ;| | .`\ || | .'
|
||||||
|
: : |.' |. ; /--` ; | ; \ ; |: : | ' |: : |-,
|
||||||
|
| ' ' ; :; | ; | : | ; | '| ' ' ; :: | ;/|
|
||||||
|
' | .'. || : | . | ' ' ' :' | ; . || : .'
|
||||||
|
| | : | '. | '___ ' ; \; / || | : | '| | |-,
|
||||||
|
' : | : ;' ; : .'| \ \ ', / ' : | / ; ' : ;/|
|
||||||
|
| | ' ,/ ' | '/ : ; : / | | '` ,/ | | \
|
||||||
|
; : ;--' | : / \ \ .' ; : .' | : .'
|
||||||
|
| ,/ \ \ .' `---` | ,.' | | ,' @Author Himit_ZH
|
||||||
|
'---' `---` '---' `----'
|
|
@ -95,6 +95,9 @@ public class Problem implements Serializable {
|
||||||
@ApiModelProperty(value = "是否默认开启该题目的测试样例结果查看")
|
@ApiModelProperty(value = "是否默认开启该题目的测试样例结果查看")
|
||||||
private Boolean openCaseResult;
|
private Boolean openCaseResult;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "题目测试数据是否是上传的")
|
||||||
|
private Boolean isUploadCase;
|
||||||
|
|
||||||
@ApiModelProperty(value = "题目测试数据的版本号")
|
@ApiModelProperty(value = "题目测试数据的版本号")
|
||||||
private String caseVersion;
|
private String caseVersion;
|
||||||
|
|
||||||
|
|
|
@ -32,20 +32,10 @@ public class UserRecord implements Serializable {
|
||||||
@ApiModelProperty(value = "用户id")
|
@ApiModelProperty(value = "用户id")
|
||||||
private String uid;
|
private String uid;
|
||||||
|
|
||||||
@ApiModelProperty(value = "总提交数")
|
|
||||||
private Integer submissions;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "cf得分")
|
@ApiModelProperty(value = "cf得分")
|
||||||
@TableField("rating")
|
@TableField("rating")
|
||||||
private Integer rating;
|
private Integer rating;
|
||||||
|
|
||||||
@ApiModelProperty(value = "IO题目总得分")
|
|
||||||
private Integer totalScore;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "乐观锁")
|
|
||||||
@Version
|
|
||||||
private Integer version;
|
|
||||||
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
@TableField(fill = FieldFill.INSERT)
|
||||||
private Date gmtCreate;
|
private Date gmtCreate;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isOpen: true,
|
isOpen: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,7 +42,7 @@ export default {
|
||||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||||
indentUnit: 4, //一个块(编辑语言中的含义)应缩进多少个空格
|
indentUnit: 4, //一个块(编辑语言中的含义)应缩进多少个空格
|
||||||
styleActiveLine: true,
|
styleActiveLine: true,
|
||||||
autofocus: true,
|
autofocus: false,
|
||||||
matchBrackets: true, //括号匹配
|
matchBrackets: true, //括号匹配
|
||||||
styleActiveLine: true,
|
styleActiveLine: true,
|
||||||
autoCloseBrackets: true,
|
autoCloseBrackets: true,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
type="search"
|
type="search"
|
||||||
size="medium"
|
size="medium"
|
||||||
@search-click="filterByKeyword"
|
@search-click="filterByKeyword"
|
||||||
|
@keyup.enter.native="filterByKeyword"
|
||||||
style="margin-bottom:10px"
|
style="margin-bottom:10px"
|
||||||
></vxe-input>
|
></vxe-input>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
|
|
|
@ -8,10 +8,31 @@
|
||||||
:autofocus="false"
|
:autofocus="false"
|
||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
codeStyle="arduino-light"
|
codeStyle="arduino-light"
|
||||||
></mavon-editor>
|
>
|
||||||
|
<template v-slot:left-toolbar-after v-if="isAdminRole">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
title="文件上传"
|
||||||
|
class="op-icon fa markdown-upload"
|
||||||
|
aria-hidden="true"
|
||||||
|
@click="uploadFile"
|
||||||
|
>
|
||||||
|
<!-- 这里用的是element-ui给出的图标 -->
|
||||||
|
<i class="el-icon-upload" />
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</mavon-editor>
|
||||||
|
<!-- 在这里放一个隐藏的input,用来选择文件 -->
|
||||||
|
<input
|
||||||
|
ref="uploadInput"
|
||||||
|
style="display: none"
|
||||||
|
type="file"
|
||||||
|
@change="uploadFileChange"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
import { addCodeBtn } from '@/common/codeblock';
|
import { addCodeBtn } from '@/common/codeblock';
|
||||||
export default {
|
export default {
|
||||||
name: 'Editor',
|
name: 'Editor',
|
||||||
|
@ -53,6 +74,34 @@ export default {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
uploadFile() {
|
||||||
|
// 通过ref找到隐藏的input标签,触发它的点击方法
|
||||||
|
this.$refs.uploadInput.click();
|
||||||
|
},
|
||||||
|
// 监听input获取文件的状态
|
||||||
|
uploadFileChange(e) {
|
||||||
|
// 获取到input选取的文件
|
||||||
|
const file = e.target.files[0];
|
||||||
|
// 创建form格式的数据,将文件放入form中
|
||||||
|
const formdata = new FormData();
|
||||||
|
formdata.append('file', file);
|
||||||
|
|
||||||
|
this.$http({
|
||||||
|
url: '/api/file/upload-md-file',
|
||||||
|
method: 'post',
|
||||||
|
data: formdata,
|
||||||
|
headers: { 'Content-Type': 'multipart/form-data' },
|
||||||
|
}).then((res) => {
|
||||||
|
// 这里获取到的是mavon编辑器实例,上面挂载着很多方法
|
||||||
|
const $vm = this.$refs.md;
|
||||||
|
// 将文件名与文件路径插入当前光标位置,这是mavon-editor 内置的方法
|
||||||
|
$vm.insertText($vm.getTextareaDom(), {
|
||||||
|
prefix: `[${file.name}](${res.data.data.link})`,
|
||||||
|
subfix: '',
|
||||||
|
str: '',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(val) {
|
value(val) {
|
||||||
|
@ -69,6 +118,9 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['isAdminRole']),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -366,15 +366,14 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="isUploadTestCase"
|
v-model="problem.isUploadCase"
|
||||||
@change="changeSampleUploadMethod"
|
|
||||||
active-text="Use Upload File"
|
active-text="Use Upload File"
|
||||||
inactive-text="Use Manual Input"
|
inactive-text="Use Manual Input"
|
||||||
style="margin: 10px 0"
|
style="margin: 10px 0"
|
||||||
>
|
>
|
||||||
</el-switch>
|
</el-switch>
|
||||||
|
|
||||||
<div v-show="isUploadTestCase">
|
<div v-show="problem.isUploadCase">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item :error="error.testcase">
|
<el-form-item :error="error.testcase">
|
||||||
<el-upload
|
<el-upload
|
||||||
|
@ -416,7 +415,7 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="!isUploadTestCase">
|
<div v-show="!problem.isUploadCase">
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-for="(sample, index) in problemSamples"
|
v-for="(sample, index) in problemSamples"
|
||||||
:key="'sample' + index"
|
:key="'sample' + index"
|
||||||
|
@ -590,6 +589,7 @@ export default {
|
||||||
uploadTestcaseDir: '',
|
uploadTestcaseDir: '',
|
||||||
testCaseScore: [],
|
testCaseScore: [],
|
||||||
isRemote: false,
|
isRemote: false,
|
||||||
|
isUploadCase: true,
|
||||||
type: 0,
|
type: 0,
|
||||||
hint: '',
|
hint: '',
|
||||||
source: '',
|
source: '',
|
||||||
|
@ -610,7 +610,6 @@ export default {
|
||||||
spjMode: '',
|
spjMode: '',
|
||||||
disableRuleType: false,
|
disableRuleType: false,
|
||||||
routeName: '',
|
routeName: '',
|
||||||
isUploadTestCase: true,
|
|
||||||
uploadTestcaseDir: '',
|
uploadTestcaseDir: '',
|
||||||
uploadFileUrl: '',
|
uploadFileUrl: '',
|
||||||
error: {
|
error: {
|
||||||
|
@ -660,6 +659,7 @@ export default {
|
||||||
spjLanguage: '',
|
spjLanguage: '',
|
||||||
spjCode: '',
|
spjCode: '',
|
||||||
spjCompileOk: false,
|
spjCompileOk: false,
|
||||||
|
isUploadCase: true,
|
||||||
uploadTestcaseDir: '',
|
uploadTestcaseDir: '',
|
||||||
testCaseScore: [],
|
testCaseScore: [],
|
||||||
contestProblem: {},
|
contestProblem: {},
|
||||||
|
@ -699,6 +699,8 @@ export default {
|
||||||
this.problemTags = []; //指定问题的标签列表
|
this.problemTags = []; //指定问题的标签列表
|
||||||
this.problemLanguages = []; //指定问题的编程语言列表
|
this.problemLanguages = []; //指定问题的编程语言列表
|
||||||
this.problemSamples = [];
|
this.problemSamples = [];
|
||||||
|
this.problemCodeTemplate = [];
|
||||||
|
this.codeTemplate = [];
|
||||||
this.init();
|
this.init();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -771,6 +773,14 @@ export default {
|
||||||
this.problem = data;
|
this.problem = data;
|
||||||
this.problem['examples'] = utils.stringToExamples(data.examples);
|
this.problem['examples'] = utils.stringToExamples(data.examples);
|
||||||
this.testCaseUploaded = true;
|
this.testCaseUploaded = true;
|
||||||
|
|
||||||
|
api.admin_getProblemCases(this.pid).then((res) => {
|
||||||
|
if (this.problem.isUploadCase) {
|
||||||
|
this.problem.testCaseScore = res.data.data;
|
||||||
|
} else {
|
||||||
|
this.problemSamples = res.data.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
if (funcName === 'admin_getContestProblem') {
|
if (funcName === 'admin_getContestProblem') {
|
||||||
api
|
api
|
||||||
|
@ -781,11 +791,6 @@ export default {
|
||||||
}
|
}
|
||||||
this.getProblemCodeTemplateAndLanguage();
|
this.getProblemCodeTemplateAndLanguage();
|
||||||
|
|
||||||
if (!this.isUploadTestCase) {
|
|
||||||
api.admin_getProblemCases(this.pid).then((res) => {
|
|
||||||
this.problemSamples = res.data.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
api.admin_getProblemTags(this.pid).then((res) => {
|
api.admin_getProblemTags(this.pid).then((res) => {
|
||||||
this.problemTags = res.data.data;
|
this.problemTags = res.data.data;
|
||||||
});
|
});
|
||||||
|
@ -810,30 +815,6 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
changeSampleUploadMethod() {
|
|
||||||
if (
|
|
||||||
!this.isUploadTestCase &&
|
|
||||||
this.problemSamples.length == 0 &&
|
|
||||||
this.mode == 'edit'
|
|
||||||
) {
|
|
||||||
this.$confirm(
|
|
||||||
'你确定要获取显示该题目的评测数据?可能该题目是使用zip上传,那么数据库默认无该测试数据!',
|
|
||||||
'注意',
|
|
||||||
{
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
api.admin_getProblemCases(this.pid).then((res) => {
|
|
||||||
this.problemSamples = res.data.data;
|
|
||||||
myMessage.success(res.data.msg);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
switchSpj() {
|
switchSpj() {
|
||||||
if (this.testCaseUploaded) {
|
if (this.testCaseUploaded) {
|
||||||
this.$confirm(
|
this.$confirm(
|
||||||
|
@ -1024,7 +1005,7 @@ export default {
|
||||||
}
|
}
|
||||||
if (!this.problem.isRemote) {
|
if (!this.problem.isRemote) {
|
||||||
// 选择手动输入
|
// 选择手动输入
|
||||||
if (!this.isUploadTestCase) {
|
if (!this.problem.isUploadCase) {
|
||||||
if (!this.problemSamples.length) {
|
if (!this.problemSamples.length) {
|
||||||
myMessage.error('评测数据不能为空!请手动输入评测数据!');
|
myMessage.error('评测数据不能为空!请手动输入评测数据!');
|
||||||
return;
|
return;
|
||||||
|
@ -1159,11 +1140,11 @@ export default {
|
||||||
problemDto['codeTemplates'] = this.problemCodeTemplate;
|
problemDto['codeTemplates'] = this.problemCodeTemplate;
|
||||||
problemDto['tags'] = problemTagList;
|
problemDto['tags'] = problemTagList;
|
||||||
problemDto['languages'] = problemLanguageList;
|
problemDto['languages'] = problemLanguageList;
|
||||||
problemDto['isUploadTestCase'] = this.isUploadTestCase;
|
problemDto['isUploadTestCase'] = this.problem.isUploadCase;
|
||||||
problemDto['uploadTestcaseDir'] = this.problem.uploadTestcaseDir;
|
problemDto['uploadTestcaseDir'] = this.problem.uploadTestcaseDir;
|
||||||
problemDto['isSpj'] = this.problem.spj;
|
problemDto['isSpj'] = this.problem.spj;
|
||||||
// 如果选择上传文件,则使用上传后的结果
|
// 如果选择上传文件,则使用上传后的结果
|
||||||
if (this.isUploadTestCase) {
|
if (this.problem.isUploadCase) {
|
||||||
problemDto['samples'] = this.problem.testCaseScore;
|
problemDto['samples'] = this.problem.testCaseScore;
|
||||||
} else {
|
} else {
|
||||||
problemDto['samples'] = this.problemSamples;
|
problemDto['samples'] = this.problemSamples;
|
||||||
|
|
|
@ -153,7 +153,7 @@
|
||||||
<p class="title">Hint</p>
|
<p class="title">Hint</p>
|
||||||
<el-card dis-hover>
|
<el-card dis-hover>
|
||||||
<div
|
<div
|
||||||
class="content"
|
class="hint-content"
|
||||||
v-html="problemData.problem.hint"
|
v-html="problemData.problem.hint"
|
||||||
v-katex
|
v-katex
|
||||||
v-highlight
|
v-highlight
|
||||||
|
@ -928,6 +928,10 @@ a {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hint-content {
|
||||||
|
font-size: 15px !important;
|
||||||
|
}
|
||||||
|
|
||||||
p.content {
|
p.content {
|
||||||
margin-left: 25px;
|
margin-left: 25px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
@ -941,6 +945,7 @@ p.content {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.example {
|
.example {
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue