From b31b8a9b3c2f46c008381f1c3a3ffa2cc88fe911 Mon Sep 17 00:00:00 2001 From: Himit_ZH <372347736@qq.com> Date: Mon, 16 Nov 2020 23:43:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AF=E9=A1=B5=E9=9D=A2=E5=88=9B?= =?UTF-8?q?=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 43 +- hoj-vue-pc/package-lock.json | 128 +++- hoj-vue-pc/package.json | 9 + hoj-vue-pc/src/App.vue | 80 +- hoj-vue-pc/src/assets/acm.jpg | Bin 0 -> 13574 bytes hoj-vue-pc/src/assets/oi.jpg | Bin 0 -> 12205 bytes hoj-vue-pc/src/common/api.js | 12 + hoj-vue-pc/src/common/constants.js | 105 ++- hoj-vue-pc/src/common/filters.js | 15 + hoj-vue-pc/src/common/highlight.js | 26 + hoj-vue-pc/src/common/katex.js | 35 + hoj-vue-pc/src/common/loading.js | 35 - hoj-vue-pc/src/common/utils.js | 34 + .../src/components/common/CodeMirror.vue | 212 ++++++ .../src/components/common/Highlight.vue | 40 + hoj-vue-pc/src/components/common/NavBar.vue | 40 +- hoj-vue-pc/src/main.js | 31 +- hoj-vue-pc/src/router/index.js | 11 +- hoj-vue-pc/src/router/routes.js | 47 +- hoj-vue-pc/src/store/contest.js | 184 +++++ hoj-vue-pc/src/store/index.js | 9 + hoj-vue-pc/src/views/Home.vue | 16 +- hoj-vue-pc/src/views/contest/ContestList.vue | 363 +++++++++ hoj-vue-pc/src/views/contest/count.vue | 83 ++ hoj-vue-pc/src/views/contest/test.vue | 82 ++ hoj-vue-pc/src/views/problem/Problem.vue | 714 ++++++++++++++++++ hoj-vue-pc/src/views/problem/ProblemList.vue | 155 ++-- hoj-vue-pc/src/views/problem/chartData.js | 120 +++ hoj-vue-pc/src/views/rank/ACMRank.vue | 167 ++++ hoj-vue-pc/src/views/rank/OIRank.vue | 153 ++++ .../src/views/status/SubmissionDetails.vue | 267 +++++++ .../src/views/status/SubmissionList.vue | 143 +++- 32 files changed, 3120 insertions(+), 239 deletions(-) create mode 100644 hoj-vue-pc/src/assets/acm.jpg create mode 100644 hoj-vue-pc/src/assets/oi.jpg create mode 100644 hoj-vue-pc/src/common/filters.js create mode 100644 hoj-vue-pc/src/common/highlight.js create mode 100644 hoj-vue-pc/src/common/katex.js delete mode 100644 hoj-vue-pc/src/common/loading.js create mode 100644 hoj-vue-pc/src/components/common/CodeMirror.vue create mode 100644 hoj-vue-pc/src/components/common/Highlight.vue create mode 100644 hoj-vue-pc/src/store/contest.js create mode 100644 hoj-vue-pc/src/views/contest/ContestList.vue create mode 100644 hoj-vue-pc/src/views/contest/count.vue create mode 100644 hoj-vue-pc/src/views/contest/test.vue create mode 100644 hoj-vue-pc/src/views/problem/Problem.vue create mode 100644 hoj-vue-pc/src/views/problem/chartData.js create mode 100644 hoj-vue-pc/src/views/rank/ACMRank.vue create mode 100644 hoj-vue-pc/src/views/rank/OIRank.vue create mode 100644 hoj-vue-pc/src/views/status/SubmissionDetails.vue diff --git a/README.md b/README.md index c1f2db65..98afd19a 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,13 @@ > 开发记录 -| 时间 | 更新内容 | 更新者 | -| ---------- | ------------------------------------------------------ | -------- | -| 2020-10-26 | 数据库设计,登录和注册接口,文档记录开始。 | Himit_ZH | -| 2020-10-28 | 用户模块接口,题目模块接口,比赛模块接口,排行模块接口 | Himit_ZH | -| 2020-10-30 | 评测模块接口,判题服务系统,初始化前端vue项目 | Himit_ZH | -| 2020-11-08 | 前端vue主页,题目列表页,登录,注册,重置密码弹窗逻辑 | Himit_ZH | +| 时间 | 更新内容 | 更新者 | +| ---------- | ------------------------------------------------------------ | -------- | +| 2020-10-26 | 数据库设计,登录和注册接口,文档记录开始。 | Himit_ZH | +| 2020-10-28 | 用户模块接口,题目模块接口,比赛模块接口,排行模块接口 | Himit_ZH | +| 2020-10-30 | 评测模块接口,判题服务系统,初始化前端vue项目 | Himit_ZH | +| 2020-11-08 | 前端vue主页,题目列表页,登录,注册,重置密码弹窗逻辑 | Himit_ZH | +| 2020-11-16 | 前端提交列表页,提交详情页,题目详情页,排行(ACM,OI)页,比赛列表页,个人主页,个人设置页 | Himit_ZH | # 二、系统架构 @@ -300,21 +301,21 @@ jugdeCase表 评测单个样例结果表 contest表 -| 列名 | 实体属性类型 | 键 | 备注 | -| ------------ | ------------ | ----------- | ------------------------------------------- | -| id | long | 主键 | auto_increment 1000起步 | -| uid | String | 外键 | 创建者id | -| title | String | | 比赛标题 | -| type | int | | Acm赛制或者Rating | -| source | int | | 比赛来源,原创为0,克隆赛为比赛id | -| auth | int | | 0为公开赛,1为私有赛(有密码),2为报名赛。 | -| pwd | string | | 比赛密码 | -| start_time | datetime | | 开始时间 | -| end_time | datetime | | 结束时间 | -| duration | int | | 比赛时长(分) | -| explain | Srting | | 比赛说明 | -| gmt_create | datetime | | 创建时间 | -| gmt_modified | datetime | | 修改时间 | +| 列名 | 实体属性类型 | 键 | 备注 | +| ------------ | ------------ | ---- | ----------------------------------------------------- | +| id | long | 主键 | auto_increment 1000起步 | +| uid | String | 外键 | 创建者id | +| title | String | | 比赛标题 | +| type | int | | Acm赛制或者Rating | +| source | int | | 比赛来源,原创为0,克隆赛为比赛id | +| auth | int | | 0为公开赛,1为私有赛(有密码),3为保护赛(有密码)。 | +| pwd | string | | 比赛密码 | +| start_time | datetime | | 开始时间 | +| end_time | datetime | | 结束时间 | +| duration | int | | 比赛时长(分) | +| explain | Srting | | 比赛说明 | +| gmt_create | datetime | | 创建时间 | +| gmt_modified | datetime | | 修改时间 | diff --git a/hoj-vue-pc/package-lock.json b/hoj-vue-pc/package-lock.json index 3bcc80ea..a12d6a97 100644 --- a/hoj-vue-pc/package-lock.json +++ b/hoj-vue-pc/package-lock.json @@ -1243,6 +1243,15 @@ "@types/node": "*" } }, + "@types/highlight.js": { + "version": "10.1.0", + "resolved": "https://registry.npm.taobao.org/@types/highlight.js/download/@types/highlight.js-10.1.0.tgz", + "integrity": "sha1-ibsMICmX16kKB70uwffQDFa7kLQ=", + "dev": true, + "requires": { + "highlight.js": "*" + } + }, "@types/http-proxy": { "version": "1.17.4", "resolved": "https://registry.npm.taobao.org/@types/http-proxy/download/@types/http-proxy-1.17.4.tgz?cache=0&sync_timestamp=1596839386031&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fhttp-proxy%2Fdownload%2F%40types%2Fhttp-proxy-1.17.4.tgz", @@ -3281,6 +3290,12 @@ "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", "dev": true }, + "highlight.js": { + "version": "9.18.3", + "resolved": "https://registry.npm.taobao.org/highlight.js/download/highlight.js-9.18.3.tgz", + "integrity": "sha1-oaCiAo1eMUniOA+Khl7oUWcD1jQ=", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1598611709087&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz", @@ -3298,6 +3313,16 @@ "integrity": "sha1-EnY+RyUb+VHLdcIB36WP8byy0Ec=", "dev": true }, + "clipboard": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/clipboard/download/clipboard-2.0.6.tgz?cache=0&sync_timestamp=1599054235610&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fclipboard%2Fdownload%2Fclipboard-2.0.6.tgz", + "integrity": "sha1-UpISlu7A/fd+rRdJQhshyWhkc3Y=", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "clipboardy": { "version": "2.3.0", "resolved": "https://registry.npm.taobao.org/clipboardy/download/clipboardy-2.3.0.tgz", @@ -3367,6 +3392,11 @@ "q": "^1.1.2" } }, + "codemirror": { + "version": "5.58.2", + "resolved": "https://registry.npm.taobao.org/codemirror/download/codemirror-5.58.2.tgz?cache=0&sync_timestamp=1603481865446&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcodemirror%2Fdownload%2Fcodemirror-5.58.2.tgz", + "integrity": "sha1-7VSheW3hSYaIvqHN1OnusYdWXRs=" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz", @@ -3430,8 +3460,7 @@ "commander": { "version": "2.20.3", "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz?cache=0&sync_timestamp=1603599636161&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.20.3.tgz", - "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=", - "dev": true + "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=" }, "commondir": { "version": "1.0.1", @@ -4181,6 +4210,11 @@ } } }, + "default-passive-events": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/default-passive-events/download/default-passive-events-2.0.0.tgz", + "integrity": "sha1-ebGqZ77LqrOLcYRptUgP75Ltpkk=" + }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz", @@ -4290,6 +4324,11 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npm.taobao.org/delegate/download/delegate-3.2.0.tgz", + "integrity": "sha1-tmtxwxWFIuirV0T3INjKDCr1kWY=" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz", @@ -4484,6 +4523,14 @@ "safer-buffer": "^2.1.0" } }, + "echarts": { + "version": "4.9.0", + "resolved": "https://registry.npm.taobao.org/echarts/download/echarts-4.9.0.tgz?cache=0&sync_timestamp=1605024811446&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fecharts%2Fdownload%2Fecharts-4.9.0.tgz", + "integrity": "sha1-qbm6oD8Doqcx5jQMVb77V6nhNH0=", + "requires": { + "zrender": "4.3.2" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz", @@ -5371,6 +5418,14 @@ } } }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npm.taobao.org/good-listener/download/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "requires": { + "delegate": "^3.1.2" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz", @@ -5537,10 +5592,9 @@ "dev": true }, "highlight.js": { - "version": "9.18.3", - "resolved": "https://registry.npm.taobao.org/highlight.js/download/highlight.js-9.18.3.tgz", - "integrity": "sha1-oaCiAo1eMUniOA+Khl7oUWcD1jQ=", - "dev": true + "version": "10.3.2", + "resolved": "https://registry.npm.taobao.org/highlight.js/download/highlight.js-10.3.2.tgz", + "integrity": "sha1-E1/TYZoAw8u4tM1tvHjVa/y8RvE=" }, "hmac-drbg": { "version": "1.0.1", @@ -6408,6 +6462,14 @@ "verror": "1.10.0" } }, + "katex": { + "version": "0.12.0", + "resolved": "https://registry.npm.taobao.org/katex/download/katex-0.12.0.tgz", + "integrity": "sha1-L7HGZdvSsEPtz4ofXFVfRr6qDLk=", + "requires": { + "commander": "^2.19.0" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npm.taobao.org/killable/download/killable-1.0.1.tgz", @@ -6486,8 +6548,7 @@ "lodash": { "version": "4.17.20", "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597335994883&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz", - "integrity": "sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=", - "dev": true + "integrity": "sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=" }, "lodash.defaultsdeep": { "version": "4.6.1", @@ -7087,6 +7148,11 @@ "path-key": "^2.0.0" } }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/nprogress/download/nprogress-0.2.0.tgz?cache=0&sync_timestamp=1587262530340&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnprogress%2Fdownload%2Fnprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + }, "nth-check": { "version": "1.0.2", "resolved": "https://registry.npm.taobao.org/nth-check/download/nth-check-1.0.2.tgz", @@ -8713,6 +8779,11 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "resize-detector": { + "version": "0.1.10", + "resolved": "https://registry.npm.taobao.org/resize-detector/download/resize-detector-0.1.10.tgz", + "integrity": "sha1-HaP5YapfkUzLz9N1LVL9Rb7raSw=" + }, "resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npm.taobao.org/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz", @@ -8849,6 +8920,11 @@ "ajv-keywords": "^3.5.2" } }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/select/download/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz", @@ -9793,6 +9869,11 @@ "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", "dev": true }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/tiny-emitter/download/tiny-emitter-2.1.0.tgz", + "integrity": "sha1-HRpW7fxRxD6GPLtTgqcjMONVVCM=" + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz", @@ -10272,11 +10353,37 @@ "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz", "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM=" }, + "vue-clipboard2": { + "version": "0.3.1", + "resolved": "https://registry.npm.taobao.org/vue-clipboard2/download/vue-clipboard2-0.3.1.tgz", + "integrity": "sha1-blUft704SImyiw2jsSKJ7WvKSJQ=", + "requires": { + "clipboard": "^2.0.0" + } + }, + "vue-codemirror-lite": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/vue-codemirror-lite/download/vue-codemirror-lite-1.0.4.tgz", + "integrity": "sha1-SKXNfRfAkUUDyM2dm1a0OOScNBA=", + "requires": { + "codemirror": "^5.22.0" + } + }, "vue-cropper": { "version": "0.5.5", "resolved": "https://registry.npm.taobao.org/vue-cropper/download/vue-cropper-0.5.5.tgz", "integrity": "sha1-m9G6Vjx/qiaKvVL7KvTGwo0zyWI=" }, + "vue-echarts": { + "version": "5.0.0-beta.0", + "resolved": "https://registry.npm.taobao.org/vue-echarts/download/vue-echarts-5.0.0-beta.0.tgz", + "integrity": "sha1-Q43UsPxczqKBcJwffGMhsFNSvfQ=", + "requires": { + "core-js": "^3.4.4", + "lodash": "^4.17.15", + "resize-detector": "^0.1.10" + } + }, "vue-hot-reload-api": { "version": "2.3.4", "resolved": "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz", @@ -11258,6 +11365,11 @@ "dev": true } } + }, + "zrender": { + "version": "4.3.2", + "resolved": "https://registry.npm.taobao.org/zrender/download/zrender-4.3.2.tgz?cache=0&sync_timestamp=1605029444182&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fzrender%2Fdownload%2Fzrender-4.3.2.tgz", + "integrity": "sha1-7HQy+UFcgsc1hLa3uMR+GwFiCcY=" } } } diff --git a/hoj-vue-pc/package.json b/hoj-vue-pc/package.json index 329d7961..bea04407 100644 --- a/hoj-vue-pc/package.json +++ b/hoj-vue-pc/package.json @@ -9,11 +9,19 @@ "dependencies": { "axios": "^0.21.0", "core-js": "^3.6.5", + "default-passive-events": "^2.0.0", + "echarts": "^4.9.0", "element-ui": "^2.14.0", "font-awesome": "^4.7.0", + "highlight.js": "^10.3.2", + "katex": "^0.12.0", "moment": "^2.29.1", + "nprogress": "^0.2.0", "vue": "^2.6.11", + "vue-clipboard2": "^0.3.1", + "vue-codemirror-lite": "^1.0.4", "vue-cropper": "^0.5.5", + "vue-echarts": "^5.0.0-beta.0", "vue-m-message": "^3.0.0", "vue-router": "^3.2.0", "vue-template-compiler": "^2.6.12", @@ -23,6 +31,7 @@ "xe-utils": "^2.8.1" }, "devDependencies": { + "@types/highlight.js": "^10.1.0", "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-vuex": "~4.5.0", diff --git a/hoj-vue-pc/src/App.vue b/hoj-vue-pc/src/App.vue index 6993998d..b02db748 100644 --- a/hoj-vue-pc/src/App.vue +++ b/hoj-vue-pc/src/App.vue @@ -25,17 +25,68 @@ export default { -moz-box-sizing: border-box; box-sizing: border-box; } + body{ + background-color: #eee; + font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,\\5FAE\8F6F\96C5\9ED1,Arial,sans-serif; + -webkit-font-smoothing: antialiased; + color: #495060; + font-size: 12px; + } + code, kbd, pre, samp { + font-family: Consolas,Menlo,Courier,monospace; + } a { text-decoration: none; background-color: transparent; color: #495060; - transition: all 0.28s ease; + outline: 0; + cursor: pointer; + transition: color .2s ease; } a:hover{ color: #2196f3; } - + .drop-menu{ + padding-top: 7px; + } + .panel-title{ + font-size: 21px; + font-weight: 500; + padding-top: 10px; + padding-bottom: 20px; + line-height: 30px; + } + .status-green{ + background-color: #19be6b!important; + color: #fff!important; + } + .status-red{ + background-color: #ed3f14!important; + color: #fff!important; + } + .status-yellow{ + background-color: #f90!important; + color: #fff!important; + } + .status-blue{ + background-color: #2d8cf0!important; + color: #fff!important; + } + .status-gray{ + background-color:#909399!important; + color: #fff!important; + } + .own-submit-row{ + background:rgb(230, 255, 223) !important; + } + .vxe-table{ + color: #495060!important; + font-size: 12px!important; + } + #nprogress .bar { + background: #66B1FF !important; + } @media screen and (min-width: 1200px) { #app { margin-top: 80px; @@ -54,7 +105,24 @@ export default { padding: 0 4%; } } + #problem-content .sample pre { + -ms-flex: 1 1 auto; + flex: 1 1 auto; + -ms-flex-item-align: stretch; + align-self: stretch; + border-style: solid; + background: #fafafa; + border-left: 2px solid #3498db; +} +.markdown-body pre { + padding: 5px 10px; + white-space: pre-wrap; + margin-top: 15px; + margin-bottom: 15px; + background: #f8f8f9; + border: 1px dashed #e9eaec; +} .footer { margin-top: 20px; margin-bottom: 10px; @@ -65,8 +133,10 @@ export default { .fadeInUp-enter-active { animation: fadeInUp .8s; } -body{ - background-color: #eee; -} + .el-menu--popup { + min-width: 120px!important; + text-align: center; + } + diff --git a/hoj-vue-pc/src/assets/acm.jpg b/hoj-vue-pc/src/assets/acm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9fb6043a385d328e374c13514263bc85a2ab2f4b GIT binary patch literal 13574 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 Ub|vNX!-QGV*0~XKSSz}p@ZB(z|Q~{^bhfI|$by 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 { + + NProgress.start(); // 每次发送请求之前判断vuex中是否存在token // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况 // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断 const token = localStorage.getItem('token') token && (config.headers.Authorization = token); + return config; }, error => { + NProgress.done(); mmMessage.error(error.response.data.mMessage); return Promise.error(error); }) @@ -30,6 +40,7 @@ axios.interceptors.request.use( // 响应拦截器 axios.interceptors.response.use( response => { + NProgress.done(); if (response.data.status === 200) { return Promise.resolve(response); } else { @@ -39,6 +50,7 @@ axios.interceptors.response.use( }, // 服务器状态码不是200的情况 error => { + NProgress.done(); if (error.response) { switch (error.response.status) { // 401: 未登录 diff --git a/hoj-vue-pc/src/common/constants.js b/hoj-vue-pc/src/common/constants.js index 93536a5e..4facc48f 100644 --- a/hoj-vue-pc/src/common/constants.js +++ b/hoj-vue-pc/src/common/constants.js @@ -1,93 +1,127 @@ export const JUDGE_STATUS = { + '-3': { + name: 'Presentation Error', + short: 'PE', + color: 'yellow', + type: 'warning', + rgb:'#f90' + }, '-2': { name: 'Compile Error', short: 'CE', color: 'yellow', - type: 'warning' + type: 'warning', + rgb:'#f90' }, '-1': { name: 'Wrong Answer', short: 'WA', color: 'red', - type: 'error' + type: 'error', + rgb:'#ed3f14' }, '0': { name: 'Accepted', short: 'AC', color: 'green', - type: 'success' + type: 'success', + rgb:'#19be6b' }, '1': { name: 'Time Limit Exceeded', short: 'TLE', color: 'red', - type: 'error' + type: 'error', + rgb:'#ed3f14' }, '2': { name: 'Time Limit Exceeded', short: 'TLE', color: 'red', - type: 'error' + type: 'error', + rgb:'#ed3f14' }, '3': { name: 'Memory Limit Exceeded', short: 'MLE', color: 'red', - type: 'error' + type: 'error', + rgb:'#ed3f14' }, '4': { name: 'Runtime Error', short: 'RE', color: 'red', - type: 'error' + type: 'error', + rgb:'#ed3f14' }, '5': { name: 'System Error', short: 'SE', - color: '#909399', - type: 'error' + color: 'gray', + type: 'info', + rgb:'#909399' }, '6': { name: 'Pending', color: 'yellow', - type: 'warning' + type: 'warning', + rgb:'#f90' }, '7': { name: 'Judging', color: 'blue', - type: 'info' + type: '', + rgb:'#2d8cf0' }, '8': { name: 'Partial Accepted', short: 'PAC', color: 'blue', - type: 'info' + type: '', + rgb:'#2d8cf0' }, '9': { name: 'Submitting', color: 'yellow', - type: 'warning' + type: 'warning', + rgb:'#f90' + } +} + +export const PROBLEM_LEVEL={ + '0':{ + name:'Easy', + color:'green' + }, + '1':{ + name:'Mid', + color:'blue' + }, + '2':{ + name:'Hard', + color:'red' } } export const CONTEST_STATUS = { - 'NOT_START': '1', - 'UNDERWAY': '0', + 'SCHEDULED': '1', + 'RUNNING': '0', 'ENDED': '-1' } export const CONTEST_STATUS_REVERSE = { '1': { - name: 'Not Started', - color: 'yellow' + name: 'Scheduled', + color: '#f90' }, '0': { - name: 'Underway', - color: 'green' + name: 'Running', + color: '#19be6b' }, '-1': { name: 'Ended', - color: 'red' + color: '#ed3f14' } } @@ -96,6 +130,30 @@ export const RULE_TYPE = { OI: 'OI' } +export const CONTEST_TYPE_REVERSE = { + '0': { + name:'Public', + color:'success', + tips:'公开赛,每个用户都可查看与提交', + submit:true, // 公开赛可看可提交 + look:true, + }, + '1':{ + name:'Private', + color:'danger', + tips:'私有赛,需要密码才可查看与提交', + submit:false, // 私有赛 必须要密码才能看和提交 + look:false, + }, + '2':{ + name:'Protect', + color:'warning', + tips:'保护赛,每个用户都可查看,提交需要密码', + submit:false, //保护赛,可以看但是不能提交,提交需要附带比赛密码 + look:true, + } +} + export const CONTEST_TYPE = { PUBLIC: 'Public', PRIVATE: 'Password Protected' @@ -119,3 +177,10 @@ export const STORAGE_KEY = { languages: 'languages' } +export function buildProblemCodeKey (problemID, contestID = null) { + if (contestID) { + return `${STORAGE_KEY.PROBLEM_CODE}_${contestID}_${problemID}` + } + return `${STORAGE_KEY.PROBLEM_CODE}_NaN_${problemID}` +} + diff --git a/hoj-vue-pc/src/common/filters.js b/hoj-vue-pc/src/common/filters.js new file mode 100644 index 00000000..6ca1b112 --- /dev/null +++ b/hoj-vue-pc/src/common/filters.js @@ -0,0 +1,15 @@ +import moment from 'moment' +import utils from './utils' +import time from './time' + +// 友好显示时间 +function fromNow (time) { + return moment(time * 3).fromNow() +} + +export default { + submissionMemory: utils.submissionMemoryFormat, + submissionTime: utils.submissionTimeFormat, + localtime: time.utcToLocal, + fromNow: fromNow +} diff --git a/hoj-vue-pc/src/common/highlight.js b/hoj-vue-pc/src/common/highlight.js new file mode 100644 index 00000000..810f057f --- /dev/null +++ b/hoj-vue-pc/src/common/highlight.js @@ -0,0 +1,26 @@ +import hljs from 'highlight.js' +import 'highlight.js/styles/atom-one-light.css' + +export default { + install (Vue, options) { + Vue.directive('highlight', { + deep: true, + bind: function (el, binding) { + Array.from(el.querySelectorAll('code')).forEach((target) => { + if (binding.value) { + target.textContent = binding.value + } + hljs.highlightBlock(target) + }) + }, + componentUpdated: function (el, binding) { + Array.from(el.querySelectorAll('code')).forEach((target) => { + if (binding.value) { + target.textContent = binding.value + } + hljs.highlightBlock(target) + }) + } + }) + } +} diff --git a/hoj-vue-pc/src/common/katex.js b/hoj-vue-pc/src/common/katex.js new file mode 100644 index 00000000..daaea3f8 --- /dev/null +++ b/hoj-vue-pc/src/common/katex.js @@ -0,0 +1,35 @@ +import 'katex' +import renderMathInElement from 'katex/contrib/auto-render/auto-render' +import 'katex/dist/katex.min.css' + +function _ () { +} + +const defaultOptions = { + errorCallback: _, + throwOnError: false, + delimiters: [ + {left: '$', right: '$', display: false}, + {left: '$$', right: '$$', display: true}, + {left: '\\[', right: '\\]', display: true}, + {left: '\\(', right: '\\)', display: false} + ] +} + +function render (el, binding) { + let options = {} + if (binding.value) { + options = binding.value.options || {} + } + Object.assign(options, defaultOptions) + renderMathInElement(el, options) +} + +export default { + install: function (Vue, options) { + Vue.directive('katex', { + bind: render, + componentUpdated: render + }) + } +} diff --git a/hoj-vue-pc/src/common/loading.js b/hoj-vue-pc/src/common/loading.js deleted file mode 100644 index c9132298..00000000 --- a/hoj-vue-pc/src/common/loading.js +++ /dev/null @@ -1,35 +0,0 @@ -import Element from 'element-ui'; - -//全局页面跳转是否启用loading -const routerLoading = true; - -//全局api接口调用是否启用loading -const apiLoading = true; - -//loading参数配置 -const loadingConfig = { - lock: true, - text: 'Loading', - spinner: 'el-icon-loading', - background: 'rgba(0, 0, 0, 0.7)' -} - - - -var loading = null ; -const loadingShow = () => { - loading = Element.Loading.service(loadingConfig); -} - -const loadingHide = () => { - loading.close(); -} - -const loadingObj={ - loadingShow, - loadingHide, - routerLoading, - apiLoading -} - -export default loadingObj \ No newline at end of file diff --git a/hoj-vue-pc/src/common/utils.js b/hoj-vue-pc/src/common/utils.js index c2f16d96..0b83623d 100644 --- a/hoj-vue-pc/src/common/utils.js +++ b/hoj-vue-pc/src/common/utils.js @@ -78,6 +78,39 @@ function downloadFile (url) { }) } +function getLanguages () { + return new Promise((resolve, reject) => { + let languages = storage.get(STORAGE_KEY.languages) + if (languages) { + resolve(languages) + }else{ + let langs = [ + { + content_type: "text/x-csrc", + description: "GCC 5.4", + name: "C", + }, + { + content_type: "text/x-c++src", + description: "G++ 5.4", + name: "C++", + }, + { content_type: "text/x-java", + description: "OpenJDK 1.8", + name: "Java", + }, + { + content_type: "text/x-python", + description: "Python 3.7", + name: "Python3", + } + ]; + storage.set(STORAGE_KEY.languages,langs); + resolve(langs); + } + }) +} + export default { @@ -87,4 +120,5 @@ export default { filterEmptyValue: filterEmptyValue, breakLongWords: breakLongWords, downloadFile: downloadFile, + getLanguages:getLanguages } diff --git a/hoj-vue-pc/src/components/common/CodeMirror.vue b/hoj-vue-pc/src/components/common/CodeMirror.vue new file mode 100644 index 00000000..2326ce26 --- /dev/null +++ b/hoj-vue-pc/src/components/common/CodeMirror.vue @@ -0,0 +1,212 @@ + + + + + + diff --git a/hoj-vue-pc/src/components/common/Highlight.vue b/hoj-vue-pc/src/components/common/Highlight.vue new file mode 100644 index 00000000..cce99f01 --- /dev/null +++ b/hoj-vue-pc/src/components/common/Highlight.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/hoj-vue-pc/src/components/common/NavBar.vue b/hoj-vue-pc/src/components/common/NavBar.vue index 5f27da62..ab647562 100644 --- a/hoj-vue-pc/src/components/common/NavBar.vue +++ b/hoj-vue-pc/src/components/common/NavBar.vue @@ -4,8 +4,10 @@