From 1e4215459e1c2e1ac5362e253d92c6f320ad139e Mon Sep 17 00:00:00 2001 From: Himit_ZH <372347736@qq.com> Date: Tue, 21 Sep 2021 18:06:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=AF=94=E8=B5=9B=E6=89=93?= =?UTF-8?q?=E5=8D=B0=E5=8A=9F=E8=83=BD=E5=92=8C=E8=B4=A6=E5=8F=B7=E9=99=90?= =?UTF-8?q?=E5=88=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docs/README.md | 2 +- docs/docs/deploy/docker.md | 74 ++ .../controller/admin/AdminUserController.java | 4 +- .../hoj/controller/admin/FileController.java | 76 ++- .../hoj/controller/oj/AccountController.java | 4 +- .../controller/oj/ContestAdminController.java | 187 +++++ .../hoj/controller/oj/ContestController.java | 97 ++- .../controller/oj/DiscussionController.java | 28 +- .../hoj/controller/oj/JudgeController.java | 2 +- .../top/hcode/hoj/dao/ContestPrintMapper.java | 16 + .../top/hcode/hoj/dao/xml/ContestMapper.xml | 2 +- .../hcode/hoj/pojo/dto/ContestPrintDto.java | 20 + .../java/top/hcode/hoj/pojo/vo/ContestVo.java | 3 + .../hoj/service/ContestPrintService.java | 12 + .../top/hcode/hoj/service/ContestService.java | 2 + .../hcode/hoj/service/ScheduleService.java | 2 + .../service/impl/ContestPrintServiceImpl.java | 17 + .../hoj/service/impl/ContestServiceImpl.java | 33 + .../hoj/service/impl/ProblemServiceImpl.java | 13 +- .../hoj/service/impl/ScheduleServiceImpl.java | 15 + .../java/top/hcode/hoj/utils/Constants.java | 2 + .../src/main/resources/logback-spring.xml | 4 - .../hcode/hoj/judge/ProblemTestCaseUtils.java | 7 +- .../src/main/resources/logback-spring.xml | 4 - .../top/hcode/hoj/pojo/entity/Contest.java | 9 + .../hcode/hoj/pojo/entity/ContestPrint.java | 50 ++ hoj-vue/src/App.vue | 27 +- hoj-vue/src/common/api.js | 23 + hoj-vue/src/common/utils.js | 2 +- .../src/components/oj/common/CodeMirror.vue | 2 +- .../src/components/oj/setting/UserInfo.vue | 4 +- hoj-vue/src/i18n/admin/en-US.js | 12 +- hoj-vue/src/i18n/admin/zh-CN.js | 11 +- hoj-vue/src/i18n/oj/en-US.js | 20 +- hoj-vue/src/i18n/oj/zh-CN.js | 22 +- hoj-vue/src/router/ojRoutes.js | 14 + hoj-vue/src/store/contest.js | 3 +- hoj-vue/src/views/admin/contest/Contest.vue | 214 ++++-- .../src/views/admin/discussion/Discussion.vue | 1 + hoj-vue/src/views/admin/general/User.vue | 19 +- .../src/views/oj/contest/ContestDetails.vue | 32 + .../oj/contest/children/ACMInfoAdmin.vue | 11 +- .../oj/contest/children/ContestAdminPrint.vue | 195 ++++++ .../oj/contest/children/ContestPrint.vue | 96 +++ .../views/oj/discussion/discussionList.vue | 2 +- hoj-vue/src/views/oj/problem/Problem.vue | 644 +++++++++++++----- .../src/views/oj/status/SubmissionDetails.vue | 31 +- 47 files changed, 1682 insertions(+), 388 deletions(-) create mode 100644 hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/ContestAdminController.java create mode 100644 hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/dao/ContestPrintMapper.java create mode 100644 hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/pojo/dto/ContestPrintDto.java create mode 100644 hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/service/ContestPrintService.java create mode 100644 hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/service/impl/ContestPrintServiceImpl.java create mode 100644 hoj-springboot/api/src/main/java/top/hcode/hoj/pojo/entity/ContestPrint.java create mode 100644 hoj-vue/src/views/oj/contest/children/ContestAdminPrint.vue create mode 100644 hoj-vue/src/views/oj/contest/children/ContestPrint.vue diff --git a/docs/docs/README.md b/docs/docs/README.md index f2d6475d..d1142b92 100644 --- a/docs/docs/README.md +++ b/docs/docs/README.md @@ -16,5 +16,5 @@ features: details: 判题使用 cgroup 隔离用户程序,网站权限控制完善 - title: 多样化 details: 独有自身判题服务,同时支持其它知名OJ题目的提交判题 -footer: MIT Licensed | Copyright © 2021.08.08 @Author Himit_ZH QQ Group:598587305 +footer: MIT Licensed | Copyright © 2021.09.21 @Author Himit_ZH QQ Group:598587305 --- \ No newline at end of file diff --git a/docs/docs/deploy/docker.md b/docs/docs/deploy/docker.md index daf0b762..83e00824 100644 --- a/docs/docs/deploy/docker.md +++ b/docs/docs/deploy/docker.md @@ -324,5 +324,79 @@ hoj-frontend: ## 四、更新最新版本 +> 2021.09.21之后部署hoj的请看下面操作 + 请在对应的docker-compose.yml当前文件夹下执行`docker-compose pull`拉取最新镜像,然后重新`docker-compose up -d`即可。 + + +> 2021.09.21之前部署hoj的请看下面操作 + +###1、修改MySQL8.0默认的密码加密方式 + +(1)进行hoj-mysql容器 + +```shell +docker exec -it hoj-mysql bash +``` + + (2) 输入对应的mysql密码,进入mysql数据库 + + 注意:-p 后面跟着数据库密码例如hoj123456 + +```shell +mysql -uroot -p数据库密码 +``` + +(3)成功进入后,执行以下命令 + +```shell +mysql> use mysql; + +mysql> grant all PRIVILEGES on *.* to root@'%' WITH GRANT OPTION; + + +mysql> ALTER user 'root'@'%' IDENTIFIED BY '数据库密码' PASSWORD EXPIRE NEVER; + + +mysql> ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password BY '数据库密码'; + + +mysql> FLUSH PRIVILEGES; +``` + +(4) 两次exit 退出mysql和容器 + +### 2、 添加hoj-mysql-checker模块 + +(1)可以选择拉取仓库最新的docker-compose.yml文件(跟部署操作一样)或者访问: + +https://gitee.com/himitzh0730/hoj-deploy/blob/master/standAlone/docker-compose.yml + +(2)或者编辑docker-compose.yml文件,手动添加新模块 + +```yaml + hoj-mysql-checker: + image: registry.cn-shenzhen.aliyuncs.com/hcode/hoj_database_checker + container_name: hoj-mysql-checker + depends_on: + - hoj-mysql + links: + - hoj-mysql:mysql + environment: + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-hoj123456} + networks: + hoj-network: + ipv4_address: 172.20.0.8 +``` + +(3) 保存后重启容器即可 + +```shell +docker-compose down + +docker-compose up -d +``` + + + diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/admin/AdminUserController.java b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/admin/AdminUserController.java index d86d70fe..2f30d748 100644 --- a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/admin/AdminUserController.java +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/admin/AdminUserController.java @@ -10,6 +10,7 @@ import org.apache.shiro.authz.annotation.RequiresAuthentication; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import top.hcode.hoj.common.result.CommonResult; import top.hcode.hoj.pojo.entity.UserInfo; @@ -136,7 +137,8 @@ public class AdminUserController { .setUuid(uuid) .setUsername(user.get(0)) .setPassword(SecureUtil.md5(user.get(1))) - .setEmail(user.get(2))); + .setEmail(StringUtils.isEmpty(user.get(2)) ? null : user.get(2)) + .setRealname(user.get(3))); userRoleList.add(new UserRole() .setRoleId(1002L) .setUid(uuid)); diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/admin/FileController.java b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/admin/FileController.java index 95c2bedc..18d8ccc8 100644 --- a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/admin/FileController.java +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/admin/FileController.java @@ -91,6 +91,9 @@ public class FileController { @Autowired private TagServiceImpl tagService; + @Autowired + private ContestPrintServiceImpl contestPrintService; + @RequestMapping("/generate-user-excel") @RequiresAuthentication @@ -140,7 +143,7 @@ public class FileController { //将文件保存指定目录 image.transferTo(FileUtil.file(Constants.File.USER_AVATAR_FOLDER.getPath() + File.separator + filename)); } catch (Exception e) { - log.error("头像文件上传异常-------------->{}", e.getMessage()); + log.error("头像文件上传异常-------------->", e); return CommonResult.errorResponse("服务器异常:头像上传失败!", CommonResult.STATUS_ERROR); } @@ -189,7 +192,6 @@ public class FileController { } - @RequestMapping(value = "/upload-carouse-img", method = RequestMethod.POST) @RequiresAuthentication @ResponseBody @@ -440,7 +442,7 @@ public class FileController { .orderByAsc("time"); List contestRecordList = contestRecordService.list(wrapper); Assert.notEmpty(contestRecordList, "比赛暂无排行榜记录!"); - List acmContestRankVoList = contestRecordService.calcACMRank(isOpenSealRank,contest,contestRecordList); + List acmContestRankVoList = contestRecordService.calcACMRank(isOpenSealRank, contest, contestRecordList); EasyExcel.write(response.getOutputStream()) .head(fileService.getContestRankExcelHead(contestProblemDisplayIDList, true)) .sheet("rank") @@ -575,7 +577,7 @@ public class FileController { // 刷新缓存 bouts.flush(); } catch (IOException e) { - log.error("下载比赛AC提交代码的压缩文件异常------------>{}", e.getMessage()); + log.error("下载比赛AC提交代码的压缩文件异常------------>", e); response.reset(); response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); @@ -681,7 +683,7 @@ public class FileController { //将文件保存指定目录 image.transferTo(FileUtil.file(Constants.File.MARKDOWN_FILE_FOLDER.getPath() + File.separator + filename)); } catch (Exception e) { - log.error("图片文件上传异常-------------->{}", e.getMessage()); + log.error("图片文件上传异常-------------->", e); return CommonResult.errorResponse("服务器异常:图片文件上传失败!", CommonResult.STATUS_ERROR); } @@ -721,7 +723,7 @@ public class FileController { //将文件保存指定目录 file.transferTo(FileUtil.file(Constants.File.MARKDOWN_FILE_FOLDER.getPath() + File.separator + filename)); } catch (Exception e) { - log.error("文件上传异常-------------->{}", e.getMessage()); + log.error("文件上传异常-------------->", e); return CommonResult.errorResponse("服务器异常:文件上传失败!", CommonResult.STATUS_ERROR); } @@ -1242,7 +1244,7 @@ public class FileController { try { threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (InterruptedException e) { - log.error("线程池异常--------------->{}", e.getMessage()); + log.error("线程池异常--------------->", e); } String fileName = "problem_export_" + System.currentTimeMillis() + ".zip"; @@ -1266,7 +1268,7 @@ public class FileController { } bouts.flush(); } catch (IOException e) { - log.error("导出题目数据的压缩文件异常------------>{}", e.getMessage()); + log.error("导出题目数据的压缩文件异常------------>", e); response.reset(); response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); @@ -1297,5 +1299,63 @@ public class FileController { } } + @GetMapping("/download-contest-print-text") + @RequiresAuthentication + @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR) + public void downloadContestPrintText(@RequestParam("id") Long id, + HttpServletResponse response) { + ContestPrint contestPrint = contestPrintService.getById(id); + String filename = contestPrint.getUsername() + "_Contest_Print.txt"; + String filePath = Constants.File.CONTEST_TEXT_PRINT_FOLDER.getPath() + File.separator +filename; + if (!FileUtil.exist(filePath)) { + FileWriter fileWriter = new FileWriter(filePath); + fileWriter.write(contestPrint.getContent()); + } + + FileReader zipFileReader = new FileReader(filePath); + BufferedInputStream bins = new BufferedInputStream(zipFileReader.getInputStream());//放到缓冲流里面 + OutputStream outs = null;//获取文件输出IO流 + BufferedOutputStream bouts = null; + try { + outs = response.getOutputStream(); + bouts = new BufferedOutputStream(outs); + response.setContentType("application/x-download"); + response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + int bytesRead = 0; + byte[] buffer = new byte[1024 * 10]; + //开始向网络传输文件流 + while ((bytesRead = bins.read(buffer, 0, 1024 * 10)) != -1) { + bouts.write(buffer, 0, bytesRead); + } + // 刷新缓存 + bouts.flush(); + } catch (IOException e) { + log.error("下载比赛打印文本文件异常------------>", e); + response.reset(); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + Map map = new HashMap<>(); + map.put("status", CommonResult.STATUS_ERROR); + map.put("msg", "下载文件失败,请重新尝试!"); + map.put("data", null); + try { + response.getWriter().println(JSONUtil.toJsonStr(map)); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + } finally { + try { + bins.close(); + if (outs != null) { + outs.close(); + } + if (bouts != null) { + bouts.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } } \ No newline at end of file diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/AccountController.java b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/AccountController.java index 38d02e2e..eda3c63b 100644 --- a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/AccountController.java +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/AccountController.java @@ -576,8 +576,8 @@ public class AccountController { String realname = (String) params.get("realname"); String nickname = (String) params.get("nickname"); - if (!StringUtils.isEmpty(realname) && realname.length() > 10) { - return CommonResult.errorResponse("真实姓名不能超过10位"); + if (!StringUtils.isEmpty(realname) && realname.length() > 50) { + return CommonResult.errorResponse("真实姓名不能超过50位"); } if (!StringUtils.isEmpty(nickname) && nickname.length() > 20) { return CommonResult.errorResponse("昵称不能超过20位"); diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/ContestAdminController.java b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/ContestAdminController.java new file mode 100644 index 00000000..83a2a08e --- /dev/null +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/ContestAdminController.java @@ -0,0 +1,187 @@ +package top.hcode.hoj.controller.oj; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authz.annotation.RequiresAuthentication; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import top.hcode.hoj.common.result.CommonResult; +import top.hcode.hoj.pojo.dto.CheckACDto; +import top.hcode.hoj.pojo.entity.Contest; +import top.hcode.hoj.pojo.entity.ContestPrint; +import top.hcode.hoj.pojo.entity.ContestRecord; +import top.hcode.hoj.pojo.vo.UserRolesVo; +import top.hcode.hoj.service.ContestRecordService; +import top.hcode.hoj.service.impl.ContestPrintServiceImpl; +import top.hcode.hoj.service.impl.ContestServiceImpl; +import top.hcode.hoj.utils.Constants; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +/** + * @Author: Himit_ZH + * @Date: 2021/9/20 13:15 + * @Description: 处理比赛管理模块的相关数据请求 + */ +@RestController +@RequestMapping("/api") +public class ContestAdminController { + + + @Autowired + private ContestServiceImpl contestService; + + @Autowired + private ContestRecordService contestRecordService; + + @Autowired + private ContestPrintServiceImpl contestPrintService; + + /** + * @MethodName getContestACInfo + * @Params * @param null + * @Description 获取各个用户的ac情况,仅限于比赛管理者可查看 + * @Return + * @Since 2021/1/17 + */ + @GetMapping("/get-contest-ac-info") + @RequiresAuthentication + public CommonResult getContestACInfo(@RequestParam("cid") Long cid, + @RequestParam(value = "currentPage", required = false) Integer currentPage, + @RequestParam(value = "limit", required = false) Integer limit, + HttpServletRequest request) { + HttpSession session = request.getSession(); + UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo"); + // 获取本场比赛的状态 + Contest contest = contestService.getById(cid); + + // 超级管理员或者该比赛的创建者,则为比赛管理者 + boolean isRoot = SecurityUtils.getSubject().hasRole("root"); + + if (!isRoot && !contest.getUid().equals(userRolesVo.getUid())) { + return CommonResult.errorResponse("对不起,你无权查看!", CommonResult.STATUS_FORBIDDEN); + } + + if (currentPage == null || currentPage < 1) currentPage = 1; + if (limit == null || limit < 1) limit = 30; + + // 获取当前比赛的,状态为ac,未被校验的排在签名 + IPage contestRecords = contestRecordService.getACInfo(currentPage, + limit, Constants.Contest.RECORD_AC.getCode(), cid, contest.getUid()); + + return CommonResult.successResponse(contestRecords, "查询成功"); + } + + + /** + * @MethodName checkContestACInfo + * @Params * @param null + * @Description 比赛管理员确定该次提交的ac情况 + * @Return + * @Since 2021/1/17 + */ + @PutMapping("/check-contest-ac-info") + @RequiresAuthentication + public CommonResult checkContestACInfo(@RequestBody CheckACDto checkACDto, + HttpServletRequest request) { + + HttpSession session = request.getSession(); + UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo"); + // 获取本场比赛的状态 + Contest contest = contestService.getById(checkACDto.getCid()); + + // 超级管理员或者该比赛的创建者,则为比赛管理者 + boolean isRoot = SecurityUtils.getSubject().hasRole("root"); + + if (!isRoot && !contest.getUid().equals(userRolesVo.getUid())) { + return CommonResult.errorResponse("对不起,你无权操作!", CommonResult.STATUS_FORBIDDEN); + } + + boolean result = contestRecordService.updateById( + new ContestRecord().setChecked(checkACDto.getChecked()).setId(checkACDto.getId())); + + if (result) { + return CommonResult.successResponse(null, "修改校验确定成功!"); + } else { + return CommonResult.errorResponse("修改校验确定失败!"); + } + + } + + + @GetMapping("/get-contest-print") + @RequiresAuthentication + public CommonResult getContestPrint(@RequestParam("cid") Long cid, + @RequestParam(value = "currentPage", required = false) Integer currentPage, + @RequestParam(value = "limit", required = false) Integer limit, + HttpServletRequest request) { + HttpSession session = request.getSession(); + UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo"); + // 获取本场比赛的状态 + Contest contest = contestService.getById(cid); + + // 超级管理员或者该比赛的创建者,则为比赛管理者 + boolean isRoot = SecurityUtils.getSubject().hasRole("root"); + + if (!isRoot && !contest.getUid().equals(userRolesVo.getUid())) { + return CommonResult.errorResponse("对不起,你无权查看!", CommonResult.STATUS_FORBIDDEN); + } + + if (currentPage == null || currentPage < 1) currentPage = 1; + if (limit == null || limit < 1) limit = 30; + + // 获取当前比赛的,未被确定的排在签名 + + IPage contestPrintIPage = new Page<>(currentPage,limit); + + QueryWrapper contestPrintQueryWrapper = new QueryWrapper<>(); + contestPrintQueryWrapper.select("id","cid","username","realname","status","gmt_create") + .eq("cid", cid) + .orderByAsc("status") + .orderByDesc("gmt_create"); + + IPage contestPrintList = contestPrintService.page(contestPrintIPage, contestPrintQueryWrapper); + + return CommonResult.successResponse(contestPrintList, "查询成功"); + } + + /** + * @param id + * @param cid + * @param request + * @MethodName checkContestStatus + * @Description 更新该打印为确定状态 + * @Return + * @Since 2021/9/20 + */ + @PutMapping("/check-contest-print-status") + @RequiresAuthentication + public CommonResult checkContestStatus(@RequestParam("id") Long id, + @RequestParam("cid") Long cid, + HttpServletRequest request) { + + HttpSession session = request.getSession(); + UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo"); + // 获取本场比赛的状态 + Contest contest = contestService.getById(cid); + + // 超级管理员或者该比赛的创建者,则为比赛管理者 + boolean isRoot = SecurityUtils.getSubject().hasRole("root"); + + if (!isRoot && !contest.getUid().equals(userRolesVo.getUid())) { + return CommonResult.errorResponse("对不起,你无权操作!", CommonResult.STATUS_FORBIDDEN); + } + + boolean result = contestPrintService.updateById(new ContestPrint().setId(id).setStatus(1)); + + if (result) { + return CommonResult.successResponse(null, "确定成功!"); + } else { + return CommonResult.errorResponse("确定失败!"); + } + } + +} \ No newline at end of file diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/ContestController.java b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/ContestController.java index 5755b866..0a81ecd5 100644 --- a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/ContestController.java +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/ContestController.java @@ -1,6 +1,7 @@ package top.hcode.hoj.controller.oj; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ReUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -8,9 +9,11 @@ import org.apache.shiro.SecurityUtils; import org.apache.shiro.authz.annotation.RequiresAuthentication; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import top.hcode.hoj.common.result.CommonResult; import top.hcode.hoj.pojo.dto.CheckACDto; +import top.hcode.hoj.pojo.dto.ContestPrintDto; import top.hcode.hoj.pojo.dto.UserReadContestAnnouncementDto; import top.hcode.hoj.pojo.entity.*; import top.hcode.hoj.pojo.vo.*; @@ -72,6 +75,9 @@ public class ContestController { @Autowired private CodeTemplateServiceImpl codeTemplateService; + @Autowired + private ContestPrintServiceImpl contestPrintService; + /** * @MethodName getContestList * @Params * @param null @@ -152,6 +158,19 @@ public class ContestController { return CommonResult.errorResponse("比赛密码错误!"); } + /** + * + * 需要校验当前比赛是否开启账号规则限制,如果有,需要对当前用户的用户名进行验证 + * + */ + + if (contest.getOpenAccountLimit() + &&!contestService.checkAccountRule(contest.getAccountLimitRule(),userRolesVo.getUsername())){ + return CommonResult.errorResponse("对不起!本次比赛只允许特定账号规则的用户参赛!",CommonResult.STATUS_ACCESS_DENIED); + } + + + QueryWrapper wrapper = new QueryWrapper().eq("cid", Long.valueOf(cidStr)) .eq("uid", userRolesVo.getUid()); if (contestRegisterService.getOne(wrapper) != null) { @@ -415,7 +434,7 @@ public class ContestController { searchStatus, searchUsername, uid, beforeContestSubmit, rule, contest.getStartTime(), sealRankTime, userRolesVo.getUid()); if (commonJudgeList.getTotal() == 0) { // 未查询到一条数据 - return CommonResult.successResponse(null, "暂无数据"); + return CommonResult.successResponse(commonJudgeList, "暂无数据"); } else { // 比赛还是进行阶段,同时不是超级管理员与比赛管理员,需要将除自己之外的提交的时间、空间、长度隐藏 @@ -578,75 +597,47 @@ public class ContestController { } + /** - * @MethodName getContestACInfo - * @Params * @param null - * @Description 获取各个用户的ac情况,仅限于比赛管理者可查看 + * @param contestPrintDto + * @param request + * @MethodName submitPrintText + * @Description 提交比赛文本打印内容 * @Return - * @Since 2021/1/17 + * @Since 2021/9/20 */ - @GetMapping("/get-contest-ac-info") + @PostMapping("/submit-print-text") @RequiresAuthentication - public CommonResult getContestACInfo(@RequestParam("cid") Long cid, - @RequestParam(value = "currentPage", required = false) Integer currentPage, - @RequestParam(value = "limit", required = false) Integer limit, - HttpServletRequest request) { + public CommonResult submitPrintText(@RequestBody ContestPrintDto contestPrintDto, + HttpServletRequest request) { HttpSession session = request.getSession(); UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo"); // 获取本场比赛的状态 - Contest contest = contestService.getById(cid); + Contest contest = contestService.getById(contestPrintDto.getCid()); // 超级管理员或者该比赛的创建者,则为比赛管理者 boolean isRoot = SecurityUtils.getSubject().hasRole("root"); - if (!isRoot && !contest.getUid().equals(userRolesVo.getUid())) { - return CommonResult.errorResponse("对不起,你无权查看!", CommonResult.STATUS_FORBIDDEN); + /** + * 需要对该比赛做判断,是否处于开始或结束状态才可以提交打印内容,同时若是私有赛需要判断是否已注册(比赛管理员包括超级管理员可以直接获取) + */ + CommonResult commonResult = contestService.checkContestAuth(contest, userRolesVo, isRoot); + + if (commonResult != null) { + return commonResult; } - - if (currentPage == null || currentPage < 1) currentPage = 1; - if (limit == null || limit < 1) limit = 30; - - // 获取当前比赛的,状态为ac,未被校验的排在签名 - IPage contestRecords = contestRecordService.getACInfo(currentPage, - limit, Constants.Contest.RECORD_AC.getCode(), cid, contest.getUid()); - - return CommonResult.successResponse(contestRecords, "查询成功"); - } - - - /** - * @MethodName checkContestACInfo - * @Params * @param null - * @Description 比赛管理员确定该次提交的ac情况 - * @Return - * @Since 2021/1/17 - */ - @PutMapping("/check-contest-ac-info") - @RequiresAuthentication - public CommonResult checkContestACInfo(@RequestBody CheckACDto checkACDto, - HttpServletRequest request) { - - HttpSession session = request.getSession(); - UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo"); - // 获取本场比赛的状态 - Contest contest = contestService.getById(checkACDto.getCid()); - - // 超级管理员或者该比赛的创建者,则为比赛管理者 - boolean isRoot = SecurityUtils.getSubject().hasRole("root"); - - if (!isRoot && !contest.getUid().equals(userRolesVo.getUid())) { - return CommonResult.errorResponse("对不起,你无权操作!", CommonResult.STATUS_FORBIDDEN); - } - - boolean result = contestRecordService.updateById( - new ContestRecord().setChecked(checkACDto.getChecked()).setId(checkACDto.getId())); + boolean result = contestPrintService.saveOrUpdate(new ContestPrint().setCid(contestPrintDto.getCid()) + .setContent(contestPrintDto.getContent()) + .setUsername(userRolesVo.getUsername()) + .setRealname(userRolesVo.getRealname())); if (result) { - return CommonResult.successResponse(null, "修改校验确定成功!"); + return CommonResult.successResponse(null, "提交成功,请等待工作人员打印!"); } else { - return CommonResult.errorResponse("修改校验确定失败!"); + return CommonResult.errorResponse("提交失败!"); } } + } \ No newline at end of file diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/DiscussionController.java b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/DiscussionController.java index 74234363..76f2e766 100644 --- a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/DiscussionController.java +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/DiscussionController.java @@ -53,9 +53,10 @@ public class DiscussionController { @RequestParam(value = "currentPage", required = false, defaultValue = "1") Integer currentPage, @RequestParam(value = "cid", required = false) Integer categoryId, @RequestParam(value = "pid", required = false) String pid, - @RequestParam(value = "onlyMine", required = false,defaultValue = "false") Boolean onlyMine, + @RequestParam(value = "onlyMine", required = false, defaultValue = "false") Boolean onlyMine, @RequestParam(value = "keyword", required = false) String keyword, - HttpServletRequest request){ + @RequestParam(value = "admin", defaultValue = "false") Boolean admin, + HttpServletRequest request) { QueryWrapper discussionQueryWrapper = new QueryWrapper<>(); @@ -79,15 +80,18 @@ public class DiscussionController { discussionQueryWrapper.eq("pid", pid); } + + boolean isAdmin = SecurityUtils.getSubject().hasRole("root") + || SecurityUtils.getSubject().hasRole("problem_admin") + || SecurityUtils.getSubject().hasRole("admin"); discussionQueryWrapper - .eq("status", 0) + .eq(!(admin && isAdmin), "status", 0) .orderByDesc("top_priority") .orderByDesc("gmt_modified") .orderByDesc("like_num") .orderByDesc("view_num"); - if (onlyMine){ - // 获取当前登录的用户 + if (onlyMine) { HttpSession session = request.getSession(); UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo"); discussionQueryWrapper.eq("uid", userRolesVo.getUid()); @@ -122,7 +126,7 @@ public class DiscussionController { return CommonResult.errorResponse("对不起,该讨论不存在!", CommonResult.STATUS_NOT_FOUND); } - if (discussion.getStatus() == 2) { + if (discussion.getStatus() == 1) { return CommonResult.errorResponse("对不起,该讨论已被封禁!", CommonResult.STATUS_FORBIDDEN); } @@ -167,11 +171,11 @@ public class DiscussionController { @PutMapping("/discussion") @RequiresPermissions("discussion_edit") @RequiresAuthentication - public CommonResult updateDiscussion(@RequestBody Discussion discussion) { + public CommonResult updateDiscussion(@RequestBody Discussion discussion) { boolean isOk = discussionService.updateById(discussion); - if (isOk){ + if (isOk) { return CommonResult.successResponse(null, "修改成功"); - }else{ + } else { return CommonResult.errorResponse("修改失败"); } } @@ -188,7 +192,7 @@ public class DiscussionController { // 如果不是是管理员,则需要附加当前用户的uid条件 if (!SecurityUtils.getSubject().hasRole("root") && !SecurityUtils.getSubject().hasRole("admin") - &&!SecurityUtils.getSubject().hasRole("problem_admin")) { + && !SecurityUtils.getSubject().hasRole("problem_admin")) { discussionUpdateWrapper.eq("uid", userRolesVo.getUid()); } boolean isOk = discussionService.remove(discussionUpdateWrapper); @@ -252,14 +256,14 @@ public class DiscussionController { /** * @MethodName addDiscussionReport - * @Params * @param uid content reporter + * @Params * @param uid content reporter * @Description 添加讨论举报 * @Return * @Since 2021/5/11 */ @PostMapping("/discussion-report") @RequiresAuthentication - public CommonResult addDiscussionReport(@RequestBody DiscussionReport discussionReport){ + public CommonResult addDiscussionReport(@RequestBody DiscussionReport discussionReport) { boolean isOk = discussionReportService.saveOrUpdate(discussionReport); if (isOk) { return CommonResult.successResponse(null, "举报成功"); diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/JudgeController.java b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/JudgeController.java index 158b0c82..e1e0b320 100644 --- a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/JudgeController.java +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/controller/oj/JudgeController.java @@ -465,7 +465,7 @@ public class JudgeController { if (commonJudgeList.getTotal() == 0) { // 未查询到一条数据 - return CommonResult.successResponse(null, "暂无数据"); + return CommonResult.successResponse(commonJudgeList, "暂无数据"); } else { return CommonResult.successResponse(commonJudgeList, "获取成功"); } diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/dao/ContestPrintMapper.java b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/dao/ContestPrintMapper.java new file mode 100644 index 00000000..98701142 --- /dev/null +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/dao/ContestPrintMapper.java @@ -0,0 +1,16 @@ +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.ContestPrint; + +/** + * @Author: Himit_ZH + * @Date: 2021/9/19 21:04 + * @Description: + */ +@Mapper +@Repository +public interface ContestPrintMapper extends BaseMapper { +} \ No newline at end of file diff --git a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/dao/xml/ContestMapper.xml b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/dao/xml/ContestMapper.xml index 93a8c4a0..41eb31ea 100644 --- a/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/dao/xml/ContestMapper.xml +++ b/hoj-springboot/DataBackup/src/main/java/top/hcode/hoj/dao/xml/ContestMapper.xml @@ -19,7 +19,7 @@ order by c.status ASC, c.start_time DESC ([\\s\\S]+?)([\\s\\S]+?)"; + let reg = "([\\s\\S]*?)([\\s\\S]*?)"; let re = RegExp(reg,"g"); let objList = [] let tmp; diff --git a/hoj-vue/src/components/oj/common/CodeMirror.vue b/hoj-vue/src/components/oj/common/CodeMirror.vue index e92f0500..353a3272 100644 --- a/hoj-vue/src/components/oj/common/CodeMirror.vue +++ b/hoj-vue/src/components/oj/common/CodeMirror.vue @@ -290,7 +290,7 @@ export default { diff --git a/hoj-vue/src/views/admin/discussion/Discussion.vue b/hoj-vue/src/views/admin/discussion/Discussion.vue index 91e13c4c..fd26004d 100644 --- a/hoj-vue/src/views/admin/discussion/Discussion.vue +++ b/hoj-vue/src/views/admin/discussion/Discussion.vue @@ -285,6 +285,7 @@ export default { let searchParams = { currentPage: page, keyword: this.keyword, + admin: true, }; api.getDiscussionList(this.pageSize, searchParams).then( (res) => { diff --git a/hoj-vue/src/views/admin/general/User.vue b/hoj-vue/src/views/admin/general/User.vue index 0ef7a951..b4541f3e 100644 --- a/hoj-vue/src/views/admin/general/User.vue +++ b/hoj-vue/src/views/admin/general/User.vue @@ -172,7 +172,8 @@