前端优化

This commit is contained in:
Himit_ZH 2020-11-24 22:03:42 +08:00
parent 98f0c2da2f
commit 95be3b5db1
63 changed files with 1349 additions and 566 deletions

View File

@ -14,6 +14,7 @@
| 2020-11-08 | 前端vue主页题目列表页登录注册重置密码弹窗逻辑 | Himit_ZH |
| 2020-11-16 | 前端提交列表页,提交详情页,题目详情页,排行(ACM,OI)页,比赛列表页,个人主页,个人设置页 | Himit_ZH |
| 2020-11-22 | 前端比赛首页,比赛题目列表,比赛排行榜,比赛公告,首页布局调整 | Himit_ZH |
| 2020-11-24 | 介绍页,导航栏移动端优化,首页优化,公告栏优化 | Himit_ZH |
# 二、系统架构

View File

@ -1,180 +0,0 @@
<template>
<div>
<NavBar></NavBar>
<div id="app">
<transition name="el-zoom-in-bottom">
<router-view></router-view>
</transition>
</div>
</div>
</template>
<script>
import NavBar from '@/components/common/NavBar'
export default {
name: 'app',
components: {
NavBar
},
}
</script>
<style>
* {
-webkit-box-sizing: border-box;
-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;
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;
}
.home-title{
color: #409EFF;
}
.oi-100,.first-ac{
background-color: #080;
color: #fff;
font-weight: 700;
}
.oi-between{
background-color: #2d8cf0;
color: #fff;
}
.ac{
background-color: #a9f5af;
color: #3c763d;
}
.oi-0,.wa{
color: #a94442;
background-color: #f2dede;
}
.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;
font-weight: 500!important;
}
.vxe-table .vxe-body--column:not(.col--ellipsis), .vxe-table .vxe-footer--column:not(.col--ellipsis), .vxe-table .vxe-header--column:not(.col--ellipsis) {
padding: 9px 0!important;
}
#nprogress .bar {
background: #66B1FF !important;
}
@media screen and (min-width: 1200px) {
#app {
margin-top: 80px;
padding: 0 4%;
}
}
@media screen and (max-width: 1200px) {
#app {
margin-top: 210px;
padding: 0 4%;
}
}
@media screen and (max-width: 768px) {
#app {
margin-top: 210px;
padding: 0 0;
}
.markdown-body img{
max-width: 100%;
}
}
@media screen and (max-width: 400px) {
#app {
margin-top: 270px;
padding: 0 0;
}
.markdown-body img{
width: 100%;
}
}
#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;
text-align: center;
font-size: small;
}
.fadeInUp-enter-active {
animation: fadeInUp .8s;
}
.el-menu--popup {
min-width: 120px!important;
text-align: center;
}
</style>

View File

@ -1,221 +0,0 @@
<template>
<div>
<div id="header">
<el-menu
:default-active="activeIndex"
mode="horizontal"
router
active-text-color="#2196f3"
text-color="#495060"
>
<div class="logo">
<el-image
style="width: 139px; height: 50px"
:src="imgUrl"
fit="scale-down"
></el-image>
</div>
<el-menu-item index="/home"
><i class="el-icon-s-home"></i>Home</el-menu-item
>
<el-menu-item index="/problem"
><i class="el-icon-s-grid"></i>Problem</el-menu-item
>
<el-menu-item index="/contest"
><i class="el-icon-trophy"></i>Contest</el-menu-item
>
<el-menu-item index="/status"
><i class="el-icon-s-marketing"></i>Status</el-menu-item
>
<el-submenu index="rank" >
<template slot="title"><i class="el-icon-s-data"></i>Rank</template>
<el-menu-item index="/acm-rank">ACM Rank</el-menu-item>
<el-menu-item index="/oi-rank">OI Rank</el-menu-item>
</el-submenu>
<el-submenu index="about">
<template slot="title"><i class="el-icon-info"></i>About</template>
<el-menu-item index="/introduction">Introduction</el-menu-item>
<el-menu-item index="/developer">Developer</el-menu-item>
</el-submenu>
<template v-if="!isAuthenticated">
<div class="btn-menu">
<el-button type="primary" round @click="handleBtnClick('Login')"
>Login
</el-button>
<el-button
round
type="danger"
@click="handleBtnClick('Register')"
style="margin-left: 5px"
>Register
</el-button>
</div>
</template>
<template v-else>
<el-dropdown
class="drop-menu"
@command="handleRoute"
placement="bottom"
trigger="click"
>
<span class="el-dropdown-link">
{{userInfo.username}}<i class="el-icon-caret-bottom"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="/user-home">Home</el-dropdown-item>
<el-dropdown-item command="/status?myself=1">Submissions</el-dropdown-item>
<el-dropdown-item command="/setting">Setting</el-dropdown-item>
<el-dropdown-item v-if="isAdminRole" command="/admin">Management</el-dropdown-item>
<el-dropdown-item divided command="/logout">Logout</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-menu>
</div>
<el-dialog
:visible.sync="modalVisible"
width="400px"
class="dialog"
:title="title"
>
<component :is="modalStatus.mode" v-if="modalVisible"></component>
<div slot="footer" style="display: none"></div>
</el-dialog>
</div>
</template>
<script>
import Login from "@/components/common/Login";
import Register from "@/components/common/Register";
import ResetPwd from "@/components/common/ResetPassword";
import { mapGetters, mapActions } from "vuex";
import api from "@/common/api";
export default {
components: {
Login,
Register,
ResetPwd,
},
mounted() {
let activeName = this.$route.path.split("/")[1];
if(activeName === ''){
this.activeIndex = '/home'
}else{
this.activeIndex = '/'+activeName
}
},
data() {
return {
activeIndex: "home",
centerDialogVisible: false,
imgUrl: require("@/assets/logo.png"),
};
},
methods: {
...mapActions(["changeModalStatus"]),
handleBtnClick(mode) {
this.changeModalStatus({
mode,
visible: true,
});
},
handleRoute (route) {
if (route && route.indexOf('admin') < 0) {
this.$router.push(route)
} else {
window.open('/admin/')
}
},
},
computed: {
...mapGetters(["modalStatus", "userInfo", "isAuthenticated", "isAdminRole","token"]),
modalVisible: {
get() {
return this.modalStatus.visible;
},
set(value) {
this.changeModalStatus({ visible: value });
},
},
title: {
get() {
if (this.modalStatus.mode == "ResetPwd") {
return "Reset Password - HOJ";
} else {
return this.modalStatus.mode + " - HOJ";
}
},
},
},
};
</script>
<style scoped>
#header {
min-width: 300px;
position: fixed;
top: 0;
left: 0;
height: auto;
width: 100%;
z-index: 1000;
background-color: #fff;
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.1);
}
.logo {
margin-left: 2%;
margin-right: 2%;
float: left;
width: 139px;
height: 42px;
margin-top: 5px;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
.el-icon-arrow-down {
font-size: 18px;
}
.drop-menu {
float: right;
margin-right: 30px;
position: relative;
font-weight: 500;
right: 10px;
margin-top: 18px;
font-size: 18px;
}
.btn-menu {
font-size: 16px;
float: right;
margin-right: 10px;
margin-top: 10px;
}
/deep/ .el-dialog {
border-radius: 10px !important;
text-align: center;
}
/deep/ .el-dialog__header .el-dialog__title {
font-size: 22px;
font-weight: 600;
font-family: Arial, Helvetica, sans-serif;
line-height: 1em;
color: #4e4e4e;
}
.el-submenu__title i {
color: #495060!important;
}
.el-menu-item i{
color: #495060;
}
.is-active .el-submenu__title i,.is-active{
color:#2196f3!important;
}
</style>

View File

@ -1,155 +0,0 @@
<template>
<div>
<el-card class="contest">
<div slot="header" class="clearfix title">
<el-link @click="goContest" :underline="false">比赛标题</el-link>
</div>
<el-carousel
indicator-position="outside"
height="200px"
:interval="interval"
>
<el-carousel-item v-for="(contest, index) in contests" :key="index">
<div class="contest-info">
<div class="contest-tags">
<el-button type="primary" round size="mini"
><i class="fa fa-calendar"></i>
{{ contest.beginTime | localtime }}
</el-button>
<el-button type="success" round size="mini"
><i class="fa fa-clock-o"></i>
{{ contest.duration }}
</el-button>
<el-button type="warning" round size="mini"
><i class="fa fa-trophy"></i>
{{ contest.type }}
</el-button>
</div>
<div class="contest-description">
<blockquote v-html="contest.description"></blockquote>
</div>
</div>
</el-carousel-item>
</el-carousel>
</el-card>
<el-row :gutter="20">
<el-col :md="12" :sm="24">
<Announcements></Announcements>
</el-col>
<el-col :md="12" :sm="24">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span class="panel-title home-title"
>Other OnlineJudge Contest</span
>
</div>
<vxe-table
border="inner"
stripe
auto-resize
:data="otherContests">
<vxe-table-column field="oj" title="OJ" min-width="100"></vxe-table-column>
<vxe-table-column field="title" title="Title" min-width="200"></vxe-table-column>
<vxe-table-column field="beginTime" title="Begin Time" min-width="150">
<template v-slot="{ row }" >
<span>{{row.beginTime| localtime}}</span>
</template>
</vxe-table-column>
<vxe-table-column field="endTime" title="End Time" min-width="150">
<template v-slot="{ row }" >
<span>{{row.endTime| localtime}}</span>
</template>
</vxe-table-column>
</vxe-table>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import time from "@/common/time";
import Announcements from "@/components/common/Announcements.vue";
export default {
name: "home",
components: {
Announcements,
},
data() {
return {
interval: 6000,
otherContests: [
{
oj: "Codeforces",
title:
"Codeforces Round #680 (Div. 1, based on VK Cup 2020-2021 - Final)",
beginTime: "2020-11-08T05:00:00Z",
endTime: "2020-11-08T08:00:00Z",
},
],
contests: [
{
beginTime: "2020-11-08T05:00:00Z",
duration: "5hours",
type: "ACM",
description: "<h1>描述</h1>",
},
],
};
},
methods: {
goContest() {},
},
filters: {
localtime(value) {
return time.utcToLocal(value);
},
},
};
</script>
<style scoped>
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 200px;
margin: 0;
}
.el-carousel__item:nth-child(n) {
background-color: #fff;
}
.el-col {
margin-top: 25px;
}
.contest {
text-align: center;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
.contest .title .el-link {
font-size: 25px;
font-weight: 500;
color: #444;
}
.clearfix h2 {
color: #409eff;
}
.el-link.el-link--default:hover {
color: #409eff;
transition: all 0.28s ease;
}
.contest .content-info {
padding: 0 70px 40px 70px;
}
.contest .contest-description {
margin-top: 25px;
}
</style>

View File

@ -2650,6 +2650,11 @@
}
}
},
"body-scroll-lock": {
"version": "2.7.1",
"resolved": "https://registry.npm.taobao.org/body-scroll-lock/download/body-scroll-lock-2.7.1.tgz",
"integrity": "sha1-yvP5yRdzrx/7aEzWbtkTe1tzcBQ="
},
"bonjour": {
"version": "3.5.0",
"resolved": "https://registry.npm.taobao.org/bonjour/download/bonjour-3.5.0.tgz",
@ -4050,6 +4055,11 @@
"assert-plus": "^1.0.0"
}
},
"dayjs": {
"version": "1.9.6",
"resolved": "https://registry.npm.taobao.org/dayjs/download/dayjs-1.9.6.tgz?cache=0&sync_timestamp=1604990508741&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdayjs%2Fdownload%2Fdayjs-1.9.6.tgz",
"integrity": "sha1-bwx312rB/2NyDdEZfly4e2eUPXA="
},
"de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz",
@ -6470,6 +6480,11 @@
"commander": "^2.19.0"
}
},
"keycode": {
"version": "2.2.0",
"resolved": "https://registry.npm.taobao.org/keycode/download/keycode-2.2.0.tgz",
"integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
},
"killable": {
"version": "1.0.1",
"resolved": "https://registry.npm.taobao.org/killable/download/killable-1.0.1.tgz",
@ -6978,6 +6993,18 @@
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
"dev": true
},
"muse-ui": {
"version": "3.0.2",
"resolved": "https://registry.npm.taobao.org/muse-ui/download/muse-ui-3.0.2.tgz",
"integrity": "sha1-8pLooGPWJdNbHc4bFQS8DMzXjmU=",
"requires": {
"body-scroll-lock": "^2.6.1",
"dayjs": "^1.8.2",
"keycode": "^2.1.9",
"normalize-wheel": "^1.0.1",
"resize-observer-polyfill": "^1.5.0"
}
},
"mz": {
"version": "2.7.0",
"resolved": "https://registry.npm.taobao.org/mz/download/mz-2.7.0.tgz",

View File

@ -16,6 +16,7 @@
"highlight.js": "^10.3.2",
"katex": "^0.12.0",
"moment": "^2.29.1",
"muse-ui": "^3.0.2",
"nprogress": "^0.2.0",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.1",

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

211
hoj-vue/src/App.vue Normal file
View File

@ -0,0 +1,211 @@
<template>
<div>
<NavBar></NavBar>
<div id="app-contest">
<transition name="el-zoom-in-bottom">
<router-view></router-view>
</transition>
</div>
<div class="footer">
<p>浙ICP备20009096号-1</p>
<p>
Powered by <a href="https://www.hcode.top" style="">HOJ</a>
<span>&nbsp; Version: 1.0</span>
</p>
</div>
<!-- <div id="app-loader">
<div class="square"></div>
<div class="square"></div>
<div class="square last"></div>
<div class="square clear"></div>
<div class="square"></div>
<div class="square last"></div>
<div class="square clear"></div>
<div class="square "></div>
<div class="square last"></div>
<div class="loader-content">
<span>Loading...</span>
</div>
</div> -->
</div>
</template>
<script>
import NavBar from "@/components/common/NavBar";
import { mapActions, mapState } from "vuex";
export default {
name: "app-contest",
components: {
NavBar,
},
watch: {
$route() {
this.changeDomTitle();
},
},
created: function () {
try {
document.body.removeChild(document.getElementById("app-loader"));
} catch (e) {
console.log(e);
}
},
};
</script>
<style>
* {
-webkit-box-sizing: border-box;
-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;
outline: 0;
cursor: pointer;
transition: color 0.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;
}
.home-title {
color: #409eff;
}
.oi-100,
.first-ac {
background-color: #080;
color: #fff;
font-weight: 700;
}
.oi-between {
background-color: #2d8cf0;
color: #fff;
}
.ac {
background-color: #a9f5af;
color: #3c763d;
}
.oi-0,
.wa {
color: #a94442;
background-color: #f2dede;
}
.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;
font-weight: 500 !important;
}
.vxe-table .vxe-body--column:not(.col--ellipsis),
.vxe-table .vxe-footer--column:not(.col--ellipsis),
.vxe-table .vxe-header--column:not(.col--ellipsis) {
padding: 9px 0 !important;
}
#nprogress .bar {
background: #66b1ff !important;
}
@media screen and (min-width: 1080px) {
#app-contest {
margin-top: 80px;
padding: 0 4%;
}
}
.markdown-body img {
max-width: 100%;
}
.contest-description img {
max-width: 100%;
}
@media screen and (max-width: 1080px) {
#app-contest {
margin-top: 20px;
padding: 0 5px;
}
.el-row {
margin-left: 0px !important;
margin-right: 0px !important;
}
.el-col {
padding-left: 0px !important;
padding-right: 0px !important;
}
}
#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;
text-align: center;
font-size: small;
}
.el-menu--popup {
min-width: 120px !important;
text-align: center;
}
</style>

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,135 @@
@-webkit-keyframes enter {
0% {
opacity: 0;
top: -10px;
}
5% {
opacity: 1;
top: 0px;
}
50.9% {
opacity: 1;
top: 0px;
}
55.9% {
opacity: 0;
top: 10px;
}
}
@keyframes enter {
0% {
opacity: 0;
top: -10px;
}
5% {
opacity: 1;
top: 0px;
}
50.9% {
opacity: 1;
top: 0px;
}
55.9% {
opacity: 0;
top: 10px;
}
}
@-moz-keyframes enter {
0% {
opacity: 0;
top: -10px;
}
5% {
opacity: 1;
top: 0px;
}
50.9% {
opacity: 1;
top: 0px;
}
55.9% {
opacity: 0;
top: 10px;
}
}
body {
background: #f8f8f9;
}
#app-loader {
position: absolute;
left: 50%;
top: 50%;
margin-left: -27.5px;
margin-top: -27.5px;
}
#app-loader .square {
background: #2d8cf0;
width: 15px;
height: 15px;
float: left;
top: -10px;
margin-right: 5px;
margin-top: 5px;
position: relative;
opacity: 0;
-webkit-animation: enter 6s infinite;
animation: enter 6s infinite;
}
#app-loader .enter {
top: 0px;
opacity: 1;
}
#app-loader .square:nth-child(1) {
-webkit-animation-delay: 1.8s;
-moz-animation-delay: 1.8s;
animation-delay: 1.8s;
}
#app-loader .square:nth-child(2) {
-webkit-animation-delay: 2.1s;
-moz-animation-delay: 2.1s;
animation-delay: 2.1s;
}
#app-loader .square:nth-child(3) {
-webkit-animation-delay: 2.4s;
-moz-animation-delay: 2.4s;
animation-delay: 2.4s;
background: #ff9900;
}
#app-loader .square:nth-child(4) {
-webkit-animation-delay: 0.9s;
-moz-animation-delay: 0.9s;
animation-delay: 0.9s;
}
#app-loader .square:nth-child(5) {
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
animation-delay: 1.2s;
}
#app-loader .square:nth-child(6) {
-webkit-animation-delay: 1.5s;
-moz-animation-delay: 1.5s;
animation-delay: 1.5s;
}
#app-loader .square:nth-child(8) {
-webkit-animation-delay: 0.3s;
-moz-animation-delay: 0.3s;
animation-delay: 0.3s;
}
#app-loader .square:nth-child(9) {
-webkit-animation-delay: 0.6s;
-moz-animation-delay: 0.6s;
animation-delay: 0.6s;
}
#app-loader .clear {
clear: both;
}
#app-loader .last {
margin-right: 0;
}
#app-loader .loader-content{
color: #3498db;
font-size: 16px;
font-weight: 600;
}

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -88,20 +88,28 @@ function getLanguages () {
content_type: "text/x-csrc",
description: "GCC 5.4",
name: "C",
compile_command: "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c11 {src_path} -lm -o {exe_path}",
template: "#include <stdio.h>\nint add(int a, int b) {\n return a+b;\n}\nint main() {\n printf(\"%d\", add(1, 2));\n return 0;\n}"
},
{
content_type: "text/x-c++src",
description: "G++ 5.4",
name: "C++",
compile_command: "/usr/bin/g++ -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c++14 {src_path} -lm -o {exe_path}",
template: "#include <iostream>\nint add(int a, int b) {\n return a+b;\n}\nint main() {\n std::cout << add(1, 2);\n return 0;\n}",
},
{ content_type: "text/x-java",
description: "OpenJDK 1.8",
name: "Java",
compile_command: "/usr/bin/javac {src_path} -d {exe_dir} -encoding UTF8",
template: "import java.util.Scanner;\npublic class Main{\n public static void main(String[] args){\n Scanner in=new Scanner(System.in);\n int a=in.nextInt();\n int b=in.nextInt();\n System.out.println((a+b));\n }\n}"
},
{
content_type: "text/x-python",
description: "Python 3.7",
name: "Python3",
template: "a, b = map(int, input().split())\nprint(a + b)",
compile_command: "/usr/bin/python3 -m py_compile {src_path}"
}
];
storage.set(STORAGE_KEY.languages,langs);

View File

@ -96,8 +96,8 @@ export default {
"username": "root",
"real_name": null
},
"title": "\u8d5e\u52a9\u672c\u7ad9\u7684\u670d\u52a1\u5668 O(\u2229_\u2229)O\u8c22\u8c22",
"content": "<p><img alt=\"IMG_0264.JPG\" src=\"/public/upload/4cd6928f19.jpg\" width=\"425\" height=\"346\" /><br /></p><p><br /></p><ul><li>\u8d5e\u52a9\u672c\u7ad9\u8d2d\u4e70\u66f4\u597d\u7684\u670d\u52a1\u5668\uff0c\u9632\u6b62\u90e8\u5206\u9898\u76ee\u548c\u7f16\u8bd1\u5668\u975e\u9884\u671f\u7684\u8d85\u65f6</li><li>\u8d5e\u52a9\u672c\u7ad9\u7684CDN</li></ul><p><span style=\"color: rgb(65, 140, 175);\">O(\u2229_\u2229)O\u8c22\u8c22</span></p>",
"title": "测试标题",
"content": "<p>\u7ef4\u4ed6\u5165\u6211\u5fc3\uff0c\u8d5b\u8fc7\u6d77\u6d1b\u56e0\uff0c\u5728\u8fd9\u4e2a\u5bd2\u51b7\u7684\u51ac\u5929\uff0c\u4e3a\u4ec0\u4e48\u4e0d\u6765\u4e00\u676f\u51b0\u723d\u67e0\u6aac\u8336\u5462\uff1f</p><p><img src=\"https://pic1.zhimg.com/d8db4bb6d8dfc727b6f0a7f12d7367a0_r.jpg?source=1940ef5c\" alt=\"\" /></p><h1>\u6bd4\u8d5b\u5956\u54c1\u8bf4\u660e:</h1><p>\u672c\u6b21\u6bd4\u8d5b\u5177\u6709\u4e30\u539a\u7684\u5956\u54c1 (\u91cd\u8981\u7684\u4e0d\u662f\u4ef7\u503c\uff0c\u800c\u662f<b>\u6b22\u4e50</b>\u4e0d\u662f\u4e48\uff1f) \uff0c\u5177\u4f53\u89c4\u5219\u5982\u4e0b\uff1a</p><p>\u4e00\u3001\u6240\u6709\u53c2\u8d5b\u9009\u624b\u5747\u83b7\u5f97<b>\u53c2\u8d5b\u7eaa\u5ff5\u5956</b>\u2014\u2014<b>\u9ea6\u65af\u5a01\u5c14\u5496\u5561\u4e00\u5305</b></p><p>\u4e8c\u3001\u672c\u6b21\u6bd4\u8d5b\u6392\u540d<b>\u7b2c\u4e00\u3001\u7b2c\u5341</b>\u7684\u9009\u624b\u5404\u83b7\u5f97LZH\u5b66\u957f\u8d5e\u52a9\u7684<b>\u7ef4\u4ed6\u67e0\u6aac\u8336\u4e09\u74f6</b></p><p><span style=\"color: rgb(51, 51, 51);\">\u4e09\u3001\u672c\u6b21\u6bd4\u8d5b\u6392\u540d<b>\u7b2c\u4e8c\u3001\u7b2c\u5341\u4e00</b>\u7684\u9009\u624b\u5404\u83b7\u5f97LZH\u5b66\u957f\u8d5e\u52a9\u7684<b>\u798f\u5efa\u9ad8\u7aef\u8336\u53f6\u4e09\u888b</b></span><br /></p><p>\u56db\u3001\u672c\u6b21\u6bd4\u8d5b<b>\u6700\u540e\u4e00\u4e2aAC</b>\u7684\u540c\u5b66\u5c06\u83b7\u5f97\u987d\u5f3a\u62fc\u640f\u5956\uff0c\u5956\u54c1\u795e\u79d8\u7684\u5f88\uff08ZXF\u8d5e\u52a9\uff09\uff0c<b>\u73b0\u573a\u63ed\u6653</b>\uff0c\u594b\u6597\u5427baby\u4eec.</p><p>\u4e94\u3001\u672c\u6b21\u6bd4\u8d5b\u83b7\u5f97<b>\u7b2c\u4e00\u540d</b>\u7684\u9009\u624b\u5c06\u83b7\u5f97ZYB\u5b66\u957f\u8d5e\u52a9\u7684<b>\u9ad8\u7aef\u8f6f\u76ae\u672c\u4e00\u4e2a</b></p><p><span style=\"color: rgb(51, 51, 51);\">\u516d\u3001\u672c\u6b21\u6bd4\u8d5b\u83b7\u5f97<b>\u7b2c\u4e8c\u3001\u4e09\u3001\u56db\u3001\u4e94\u540d</b>\u7684\u9009\u624b\u5c06\u6bcf\u4eba\u83b7\u5f97LZH\u5b66\u957f\u8d5e\u52a9\u7684<b>\u8f6f\u76ae\u672c\u4e00\u4e2a</b></span><br /></p><p><span style=\"color: rgb(51, 51, 51);\"><span style=\"color: rgb(51, 51, 51);\">\u4e03\u3001\u672c\u6b21\u6bd4\u8d5b\u83b7\u5f97</span><span style=\"color: rgb(51, 51, 51);\"><b>\u7b2c\u516d\u3001\u4e03\u3001\u516b\u3001\u4e5d\u540d</b></span><span style=\"color: rgb(51, 51, 51);\">\u7684\u9009\u624b\u5c06\u6bcf\u4eba\u83b7\u5f97CGX\u8d5e\u52a9\u7684<b>\u53cc\u6c47\u8089\u5757\u738b\u7279\u7ea7\u706b\u817f\u80a0</b></span><span style=\"color: rgb(51, 51, 51);\"><b>\u4e00\u6839</b></span><br /></span></p><p>\u516b\u3001\u6bd4\u8d5b\u7ed3\u675f\u540e\uff0c<b>\u968f\u673a\u62bd\u53d6\u4e09\u540d\u540c\u5b66</b>\u9001<b>\u725b\u5ba2\u886c\u886b</b>\uff0c\u6ee1\u8db3\u4f60\u6c38\u8fdc\u62bd\u4e0d\u5230\u886c\u886b\u7684\u975e\u914b\u7684\u613f\u671b\uff01</p><p><b><u>\u4ee5\u4e0a\u89c4\u5219\u6700\u7ec8\u89e3\u91ca\u6743\u5f52\u521b\u65b0\u5b9e\u9a8c\u5ba4\u6240\u6709</u></b>\u3002</p><h1><font>\u7f5a\u65f6\u89c4\u5219\u548c\u8fd4\u56de\u7ed3\u679c\u89e3\u91ca:</font></h1><p><font>1.\u63d0\u4ea4\u663e\u793aAccepted\u5373\u4e3a\u901a\u8fc7,\u82e5\u663e\u793a\u5176\u4ed6\u7ed3\u679c\u5373\u8868\u793a\u9519\u8bef.\u9519\u8bef\u4e00\u6b21\u603b\u7f5a\u65f6+20\u5206\u949f,\u8bf7\u8c28\u614e\u63d0\u4ea4\uff01</font></p><p><font>2.\u5173\u4e8e\u8fd4\u56de\u7ed3\u679c\u7684\u89e3\u91ca:</font></p><p><font>Pending & Juding : You solution will be judged soon, please wait for result</font></p><p><font>Compile Error : Failed to compile your source code. Click on the link to see compiler&#039;s output.</font></p><p><font>Accepted : Congratulations. Your solution is correct.</font></p><p><font>Wrong Answer : Your program&#039;s output doesn&#039;t match judger&#039;s answer.</font></p><p><font>Runtime Error : Your program terminated abnormally. Possible reasons are: segment fault, divided by zero or exited with code other than 0.OrThe memory your program actually used has exceeded limit.</font></p><p><font>Time Limit Exceeded : The CPU time your program used has exceeded limit. Java has a triple time limit.</font></p><p><font>Memory Limit Exceeded : The memory your program actually used has exceeded limit.</font></p><p><font>System Error : Oops, something has gone wrong with the judger. Please report this to administrator.</font></p><h1><font>\u6bd4\u8d5b\u8981\u6c42:</font></h1><p><font>\u6bd4\u8d5b\u8fc7\u7a0b\u4e2d<b>\u4e0d\u8bb8\u8ba8\u8bba</b>\u4e0d\u8bb8\u4e0a\u5916\u7f51,\u6709\u95ee\u9898\u53ef\u4ee5\u4e3e\u624b!</font></p><p><font><b>\u9898\u76ee\u96be\u5ea6\u4e0e\u9898\u76ee\u987a\u5e8f\u65e0\u5173,\u8bf7\u5408\u7406\u5b89\u6392\u505a\u9898\u65f6\u95f4!</b></font></p>",
"create_time": "2019-06-06T11:37:14.950009Z",
"last_update_time": "2019-10-10T14:08:25.887019Z",
"visible": true

View File

@ -0,0 +1,383 @@
<template>
<div>
<div id="header" v-if="!mobileNar">
<el-menu
:default-active="activeIndex"
mode="horizontal"
router
active-text-color="#2196f3"
text-color="#495060"
>
<div class="logo">
<el-image
style="width: 139px; height: 50px"
:src="imgUrl"
fit="scale-down"
></el-image>
</div>
<el-menu-item index="/home"
><i class="el-icon-s-home"></i>Home</el-menu-item
>
<el-menu-item index="/problem"
><i class="el-icon-s-grid"></i>Problem</el-menu-item
>
<el-menu-item index="/contest"
><i class="el-icon-trophy"></i>Contest</el-menu-item
>
<el-menu-item index="/status"
><i class="el-icon-s-marketing"></i>Status</el-menu-item
>
<el-submenu index="rank">
<template slot="title"><i class="el-icon-s-data"></i>Rank</template>
<el-menu-item index="/acm-rank">ACM Rank</el-menu-item>
<el-menu-item index="/oi-rank">OI Rank</el-menu-item>
</el-submenu>
<el-submenu index="about">
<template slot="title"><i class="el-icon-info"></i>About</template>
<el-menu-item index="/introduction">Introduction</el-menu-item>
<el-menu-item index="/developer">Developer</el-menu-item>
</el-submenu>
<template v-if="!isAuthenticated">
<div class="btn-menu">
<el-button type="primary" round @click="handleBtnClick('Login')"
>Login
</el-button>
<el-button
round
type="danger"
@click="handleBtnClick('Register')"
style="margin-left: 5px"
>Register
</el-button>
</div>
</template>
<template v-else>
<el-dropdown
class="drop-menu"
@command="handleRoute"
placement="bottom"
trigger="click"
>
<span class="el-dropdown-link">
{{ userInfo.username }}<i class="el-icon-caret-bottom"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="/user-home">Home</el-dropdown-item>
<el-dropdown-item command="/status?myself=1"
>Submissions</el-dropdown-item
>
<el-dropdown-item command="/setting">Setting</el-dropdown-item>
<el-dropdown-item v-if="isAdminRole" command="/admin"
>Management</el-dropdown-item
>
<el-dropdown-item divided command="/logout"
>Logout</el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-menu>
</div>
<div v-else style="top:0px;left:0px;">
<mu-appbar class="mobile-nav" color="primary">
<mu-button icon slot="left" @click="opendrawer = !opendrawer">
<i class="el-icon-s-unfold"></i>
</mu-button>
HOJ
<mu-button flat slot="right" @click="handleBtnClick('Login')"
>Login</mu-button
>
<mu-button flat slot="right" @click="handleBtnClick('Register')"
>Register</mu-button
>
<mu-menu slot="right" v-show="loginshow" :open.sync="openusermenu">
<mu-button flat>
{{ userInfo.username }}<i class="el-icon-caret-bottom"></i>
</mu-button>
<mu-list slot="content" @change="handleCommand">
<mu-list-item button value="/user-home">
<mu-list-item-content>
<mu-list-item-title>Home</mu-list-item-title>
</mu-list-item-content>
</mu-list-item>
<mu-list-item button value="/status?myself=1">
<mu-list-item-content>
<mu-list-item-title>Submissions</mu-list-item-title>
</mu-list-item-content>
</mu-list-item>
<mu-list-item button value="/setting">
<mu-list-item-content>
<mu-list-item-title>Setting</mu-list-item-title>
</mu-list-item-content>
</mu-list-item>
<mu-list-item button value="/admin">
<mu-list-item-content>
<mu-list-item-title>Management</mu-list-item-title>
</mu-list-item-content>
</mu-list-item>
<mu-divider></mu-divider>
<mu-list-item button value="/logout">
<mu-list-item-content>
<mu-list-item-title>Logout</mu-list-item-title>
</mu-list-item-content>
</mu-list-item>
</mu-list>
</mu-menu>
</mu-appbar>
<mu-appbar style="width: 100%;"> <!--占位刚好占领导航栏的高度-->
</mu-appbar>
<mu-drawer :open.sync="opendrawer" :docked="false" :right="false">
<mu-list @change="opendrawer = false">
<mu-list-item button to="/home">
<mu-list-item-action>
<i class="el-icon-s-home" style="font-size: 20px;"></i>
</mu-list-item-action>
<mu-list-item-title>Home</mu-list-item-title>
</mu-list-item>
<mu-list-item button to="/problem">
<mu-list-item-action>
<i class="el-icon-s-grid" style="font-size: 20px;"></i>
</mu-list-item-action>
<mu-list-item-title>Problem</mu-list-item-title>
</mu-list-item>
<mu-list-item button to="/contest">
<mu-list-item-action>
<i class="el-icon-trophy" style="font-size: 20px;"></i>
</mu-list-item-action>
<mu-list-item-title>Contest</mu-list-item-title>
</mu-list-item>
<mu-list-item button to="/status">
<mu-list-item-action>
<i class="el-icon-s-marketing" style="font-size: 20px;"></i>
</mu-list-item-action>
<mu-list-item-title>Status</mu-list-item-title>
</mu-list-item>
<mu-list-item button to="/acm-rank">
<mu-list-item-action>
<i class="el-icon-s-data" style="font-size: 20px;"></i>
</mu-list-item-action>
<mu-list-item-title>Rank-ACM</mu-list-item-title>
</mu-list-item>
<mu-list-item button to="/oi-rank">
<mu-list-item-action>
<i class="el-icon-data-analysis" style="font-size: 20px;"></i>
</mu-list-item-action>
<mu-list-item-title>Rank-OI</mu-list-item-title>
</mu-list-item>
<mu-list-item button to="/introduction" style="font-size: 20px;">
<mu-list-item-action>
<i class="el-icon-info"></i>
</mu-list-item-action>
<mu-list-item-title>About-Introduction</mu-list-item-title>
</mu-list-item>
<mu-list-item button to="/developer" style="font-size: 20px;">
<mu-list-item-action>
<i class="el-icon-user-solid"></i>
</mu-list-item-action>
<mu-list-item-title>About-Developer</mu-list-item-title>
</mu-list-item>
</mu-list>
</mu-drawer>
</div>
<el-dialog
:visible.sync="modalVisible"
width="400px"
class="dialog"
:title="title"
>
<component :is="modalStatus.mode" v-if="modalVisible"></component>
<div slot="footer" style="display: none"></div>
</el-dialog>
</div>
</template>
<script>
import Login from "@/components/common/Login";
import Register from "@/components/common/Register";
import ResetPwd from "@/components/common/ResetPassword";
import { mapGetters, mapActions } from "vuex";
import api from "@/common/api";
export default {
components: {
Login,
Register,
ResetPwd,
},
mounted() {
let activeName = this.$route.path.split("/")[1];
if (activeName === "") {
this.activeIndex = "/home";
} else {
this.activeIndex = "/" + activeName;
}
window.onresize = () => {
this.page_width();
};
this.page_width();
},
data() {
return {
activeIndex: "home",
centerDialogVisible: false,
mobileNar: false,
opendrawer:false,
imgUrl: require("@/assets/logo.png"),
};
},
methods: {
...mapActions(["changeModalStatus"]),
page_width() {
let screenWidth = window.screen.width;
if (screenWidth < 1080) {
this.mobileNar = true;
} else {
this.mobileNar = false;
}
},
handleBtnClick(mode) {
this.changeModalStatus({
mode,
visible: true,
});
},
handleRoute(route) {
//
if (route && route.indexOf("admin") < 0) {
this.$router.push(route);
} else {
window.open("/admin/");
}
},
handleCommand(command) {
//
},
},
computed: {
...mapGetters([
"modalStatus",
"userInfo",
"isAuthenticated",
"isAdminRole",
"token",
]),
modalVisible: {
get() {
return this.modalStatus.visible;
},
set(value) {
this.changeModalStatus({ visible: value });
},
},
title: {
get() {
if (this.modalStatus.mode == "ResetPwd") {
return "Reset Password - HOJ";
} else {
return this.modalStatus.mode + " - HOJ";
}
},
},
},
};
</script>
<style scoped>
#header {
min-width: 300px;
position: fixed;
top: 0;
left: 0;
height: auto;
width: 100%;
z-index: 1000;
background-color: #fff;
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.1);
}
.mobile-nav {
position: fixed;
left: 0px;
top: 0px;
z-index: 1000;
height: auto;
width: 100%;
}
#drawer {
position: fixed;
left: 0px;
bottom: 0px;
z-index: 1000;
width: 100%;
box-shadow: 00px 0px 00px rgb(255, 255, 255),
0px 0px 10px rgb(255, 255, 255),
0px 0px 0px rgb(255, 255, 255),
1px 1px 0px rgb(218, 218, 218);
}
.logo {
margin-left: 2%;
margin-right: 2%;
float: left;
width: 139px;
height: 42px;
margin-top: 5px;
}
.el-dropdown-link {
cursor: pointer;
color: #409eff;
}
.el-icon-arrow-down {
font-size: 18px;
}
.drop-menu {
float: right;
margin-right: 30px;
position: relative;
font-weight: 500;
right: 10px;
margin-top: 18px;
font-size: 18px;
}
.btn-menu {
font-size: 16px;
float: right;
margin-right: 10px;
margin-top: 10px;
}
/deep/ .el-dialog {
border-radius: 10px !important;
text-align: center;
}
/deep/ .el-dialog__header .el-dialog__title {
font-size: 22px;
font-weight: 600;
font-family: Arial, Helvetica, sans-serif;
line-height: 1em;
color: #4e4e4e;
}
.el-submenu__title i {
color: #495060 !important;
}
.el-menu-item i {
color: #495060;
}
.is-active .el-submenu__title i,
.is-active {
color: #2196f3 !important;
}
</style>

View File

@ -3,6 +3,11 @@ import App from './App.vue'
import router from './router'
import store from './store'
import Element from 'element-ui'
import MuseUI from 'muse-ui';
import 'muse-ui/dist/muse-ui.css';
import "element-ui/lib/theme-chalk/index.css"
import 'font-awesome/css/font-awesome.min.css'
import 'default-passive-events'
@ -42,6 +47,7 @@ Vue.use(VXETable) // 表格组件
Vue.use(VueClipboard) // 剪贴板
Vue.use(highlight) // 代码高亮
Vue.use(Element)
Vue.use(MuseUI) // 移动端导航栏需要该组件
Vue.use(VueCropper)
Vue.use(Message, { name: 'msg' }) // `Vue.prototype.$msg` 全局消息提示

View File

@ -14,6 +14,8 @@ import ContestDetails from "@/views/contest/ContestDetails.vue"
import ContestProblemList from "@/views/contest/children/ContestProblemList.vue"
import ContestRank from "@/views/contest/children/ContestRank.vue"
import Announcements from "@/components/common/Announcements.vue"
import Introduction from "@/views/about/Introduction.vue"
import NotFound from "@/views/404.vue"
const routes = [
{
path: '/',
@ -122,5 +124,15 @@ const routes = [
// }
]
},
{
path: '/introduction',
meta: {title: 'Introduction'},
component:Introduction
},
{
path: '*',
meta: {title: '404'},
component:NotFound
}
]
export default routes

259
hoj-vue/src/views/404.vue Normal file
View File

@ -0,0 +1,259 @@
<template>
<el-card shadow>
<div class="error">
<div class="container-floud">
<div style="text-align: center">
<div class="container-error-404">
<div class="clip">
<div class="shadow">
<span class="digit thirdDigit">{{thirdDigit}}</span>
</div>
</div>
<div class="clip">
<div class="shadow">
<span class="digit secondDigit">{{secondDigit}}</span>
</div>
</div>
<div class="clip">
<div class="shadow">
<span class="digit firstDigit">{{firstDigit}}</span>
</div>
</div>
<div class="msg">
OH!
<span class="triangle"></span>
</div>
</div>
<h2 class="h1">很抱歉你访问的页面找不到了</h2>
<el-button @click="goHome" size="large" style="width: 150px;">
<i class="el-icon-s-home"></i> Go Home
</el-button>
<el-button @click="backPage" size="large" style="width: 150px;margin-left: 40px;" type="primary">
<i class="el-icon-back"></i> Back
</el-button>
</div>
</div>
</div>
</el-card>
</template>
<script>
export default {
name: "NotFound404",
data(){
return{
firstDigit:null,
secondDigit:null,
thirdDigit:null
}
},
mounted(){
this.init()
},
methods: {
backPage() {
this.$router.go(-1);
},
goHome() {
this.$router.push({
name: "Home",
});
},
init() {
var loop1,
loop2,
loop3,
time = 30,
i = 0,
number;
loop3 = setInterval(()=> {
if (i > 40) {
clearInterval(loop3);
this.thirdDigit = 4;
} else {
this.thirdDigit = Math.floor(Math.random() * 9) + 1;
i++;
}
}, time);
loop2 = setInterval(()=> {
if (i > 80) {
clearInterval(loop2);
this.secondDigit = 0;
} else {
this.secondDigit= Math.floor(Math.random() * 9) + 1;
i++;
}
}, time);
loop1 = setInterval(()=> {
if (i > 100) {
clearInterval(loop1);
this.firstDigit = 4;
} else {
this.firstDigit = Math.floor(Math.random() * 9) + 1;
i++;
}
}, time);
},
},
};
</script>
<style scoped>
.error .clip .shadow {
height: 180px;
}
.error .clip:nth-of-type(2) .shadow {
width: 130px;
}
.error .clip:nth-of-type(1) .shadow,
.error .clip:nth-of-type(3) .shadow {
width: 250px;
}
.error .digit {
width: 150px;
height: 150px;
line-height: 150px;
font-size: 120px;
font-weight: bold;
}
.error h2 {
font-size: 32px;
}
.error .msg {
top: -190px;
left: 30%;
width: 80px;
height: 80px;
line-height: 80px;
font-size: 32px;
}
.error span.triangle {
top: 70%;
right: 0%;
border-left: 20px solid #535353;
border-top: 15px solid transparent;
border-bottom: 15px solid transparent;
}
.error .container-error-404 {
margin:0 auto;
position: relative;
height: 250px;
padding-top: 40px;
}
.error .container-error-404 .clip {
display: inline-block;
transform: skew(-45deg);
}
.error .clip .shadow {
overflow: hidden;
}
.error .clip:nth-of-type(2) .shadow {
overflow: hidden;
position: relative;
box-shadow: inset 20px 0px 20px -15px rgba(150, 150, 150, 0.8),
20px 0px 20px -15px rgba(150, 150, 150, 0.8);
}
.error .clip:nth-of-type(3) .shadow:after,
.error .clip:nth-of-type(1) .shadow:after {
content: "";
position: absolute;
right: -8px;
bottom: 0px;
z-index: 9999;
height: 100%;
width: 10px;
background: linear-gradient(
90deg,
transparent,
rgba(173, 173, 173, 0.8),
transparent
);
border-radius: 50%;
}
.error .clip:nth-of-type(3) .shadow:after {
left: -8px;
}
.error .digit {
position: relative;
top: 8%;
color: white;
background: #1e9fff;
border-radius: 50%;
display: inline-block;
transform: skew(45deg);
}
.error .clip:nth-of-type(2) .digit {
left: -10%;
}
.error .clip:nth-of-type(1) .digit {
right: -20%;
}
.error .clip:nth-of-type(3) .digit {
left: -20%;
}
.error h2 {
font-size: 24px;
color: #a2a2a2;
font-weight: bold;
padding-bottom: 20px;
}
.error .tohome {
font-size: 16px;
color: #07b3f9;
}
.error .msg {
position: relative;
z-index: 9999;
display: block;
background: #535353;
color: #a2a2a2;
border-radius: 50%;
font-style: italic;
}
.error .triangle {
position: absolute;
z-index: 999;
transform: rotate(45deg);
content: "";
width: 0;
height: 0;
}
@media (max-width: 767px) {
.error .clip .shadow {
height: 100px;
}
.error .clip:nth-of-type(2) .shadow {
width: 80px;
}
.error .clip:nth-of-type(1) .shadow,
.error .clip:nth-of-type(3) .shadow {
width: 100px;
}
.error .digit {
width: 80px;
height: 80px;
line-height: 80px;
font-size: 52px;
}
.error h2 {
font-size: 18px;
}
.error .msg {
top: -110px;
left: 15%;
width: 40px;
height: 40px;
line-height: 40px;
font-size: 18px;
}
.error span.triangle {
top: 70%;
right: -3%;
border-left: 10px solid #535353;
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
}
.error .container-error-404 {
height: 150px;
}
}
</style>

165
hoj-vue/src/views/Home.vue Normal file
View File

@ -0,0 +1,165 @@
<template>
<div>
<el-card class="contest">
<div slot="header" class="clearfix title">
<el-link @click="goContest" :underline="false">比赛标题</el-link>
</div>
<el-carousel
indicator-position="outside"
height="350px"
:interval="interval"
>
<el-carousel-item v-for="(contest, index) in contests" :key="index">
<div class="contest-info">
<div class="contest-tags">
<el-button type="primary" round size="mini" style="margin-top: 4px;"
><i class="fa fa-calendar"></i>
{{ contest.beginTime | localtime }}
</el-button>
<el-button type="success" round size="mini" style="margin-top: 4px;"
><i class="fa fa-clock-o"></i>
{{ contest.duration }}
</el-button>
<el-button type="warning" round size="mini" style="margin-top: 4px;"
><i class="fa fa-trophy"></i>
{{ contest.type }}
</el-button>
</div>
<div class="contest-description">
<blockquote v-html="contest.description"></blockquote>
</div>
</div>
</el-carousel-item>
</el-carousel>
</el-card>
<el-row :gutter="20">
<el-col :md="12" :sm="24">
<Announcements></Announcements>
</el-col>
<el-col :md="12" :sm="24">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span class="panel-title home-title"
>Other OnlineJudge Contest</span
>
</div>
<vxe-table
border="inner"
stripe
auto-resize
:data="otherContests">
<vxe-table-column field="oj" title="OJ" min-width="100"></vxe-table-column>
<vxe-table-column field="title" title="Title" min-width="200"></vxe-table-column>
<vxe-table-column field="beginTime" title="Begin Time" min-width="150">
<template v-slot="{ row }" >
<span>{{row.beginTime| localtime}}</span>
</template>
</vxe-table-column>
<vxe-table-column field="endTime" title="End Time" min-width="150">
<template v-slot="{ row }" >
<span>{{row.endTime| localtime}}</span>
</template>
</vxe-table-column>
</vxe-table>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import time from "@/common/time";
import Announcements from "@/components/common/Announcements.vue";
export default {
name: "home",
components: {
Announcements,
},
data() {
return {
interval: 6000,
otherContests: [
{
oj: "Codeforces",
title:
"Codeforces Round #680 (Div. 1, based on VK Cup 2020-2021 - Final)",
beginTime: "2020-11-08T05:00:00Z",
endTime: "2020-11-08T08:00:00Z",
},
],
contests: [
{
beginTime: "2020-11-08T05:00:00Z",
duration: "5hours",
type: "ACM",
description: "<p>\u7ef4\u4ed6\u5165\u6211\u5fc3\uff0c\u8d5b\u8fc7\u6d77\u6d1b\u56e0\uff0c\u5728\u8fd9\u4e2a\u5bd2\u51b7\u7684\u51ac\u5929\uff0c\u4e3a\u4ec0\u4e48\u4e0d\u6765\u4e00\u676f\u51b0\u723d\u67e0\u6aac\u8336\u5462\uff1f</p><p><img src=\"https://pic1.zhimg.com/d8db4bb6d8dfc727b6f0a7f12d7367a0_r.jpg?source=1940ef5c\" alt=\"\" /></p><h1>\u6bd4\u8d5b\u5956\u54c1\u8bf4\u660e:</h1><p>\u672c\u6b21\u6bd4\u8d5b\u5177\u6709\u4e30\u539a\u7684\u5956\u54c1 (\u91cd\u8981\u7684\u4e0d\u662f\u4ef7\u503c\uff0c\u800c\u662f<b>\u6b22\u4e50</b>\u4e0d\u662f\u4e48\uff1f) \uff0c\u5177\u4f53\u89c4\u5219\u5982\u4e0b\uff1a</p><p>\u4e00\u3001\u6240\u6709\u53c2\u8d5b\u9009\u624b\u5747\u83b7\u5f97<b>\u53c2\u8d5b\u7eaa\u5ff5\u5956</b>\u2014\u2014<b>\u9ea6\u65af\u5a01\u5c14\u5496\u5561\u4e00\u5305</b></p><p>\u4e8c\u3001\u672c\u6b21\u6bd4\u8d5b\u6392\u540d<b>\u7b2c\u4e00\u3001\u7b2c\u5341</b>\u7684\u9009\u624b\u5404\u83b7\u5f97LZH\u5b66\u957f\u8d5e\u52a9\u7684<b>\u7ef4\u4ed6\u67e0\u6aac\u8336\u4e09\u74f6</b></p><p><span style=\"color: rgb(51, 51, 51);\">\u4e09\u3001\u672c\u6b21\u6bd4\u8d5b\u6392\u540d<b>\u7b2c\u4e8c\u3001\u7b2c\u5341\u4e00</b>\u7684\u9009\u624b\u5404\u83b7\u5f97LZH\u5b66\u957f\u8d5e\u52a9\u7684<b>\u798f\u5efa\u9ad8\u7aef\u8336\u53f6\u4e09\u888b</b></span><br /></p><p>\u56db\u3001\u672c\u6b21\u6bd4\u8d5b<b>\u6700\u540e\u4e00\u4e2aAC</b>\u7684\u540c\u5b66\u5c06\u83b7\u5f97\u987d\u5f3a\u62fc\u640f\u5956\uff0c\u5956\u54c1\u795e\u79d8\u7684\u5f88\uff08ZXF\u8d5e\u52a9\uff09\uff0c<b>\u73b0\u573a\u63ed\u6653</b>\uff0c\u594b\u6597\u5427baby\u4eec.</p><p>\u4e94\u3001\u672c\u6b21\u6bd4\u8d5b\u83b7\u5f97<b>\u7b2c\u4e00\u540d</b>\u7684\u9009\u624b\u5c06\u83b7\u5f97ZYB\u5b66\u957f\u8d5e\u52a9\u7684<b>\u9ad8\u7aef\u8f6f\u76ae\u672c\u4e00\u4e2a</b></p><p><span style=\"color: rgb(51, 51, 51);\">\u516d\u3001\u672c\u6b21\u6bd4\u8d5b\u83b7\u5f97<b>\u7b2c\u4e8c\u3001\u4e09\u3001\u56db\u3001\u4e94\u540d</b>\u7684\u9009\u624b\u5c06\u6bcf\u4eba\u83b7\u5f97LZH\u5b66\u957f\u8d5e\u52a9\u7684<b>\u8f6f\u76ae\u672c\u4e00\u4e2a</b></span><br /></p><p><span style=\"color: rgb(51, 51, 51);\"><span style=\"color: rgb(51, 51, 51);\">\u4e03\u3001\u672c\u6b21\u6bd4\u8d5b\u83b7\u5f97</span><span style=\"color: rgb(51, 51, 51);\"><b>\u7b2c\u516d\u3001\u4e03\u3001\u516b\u3001\u4e5d\u540d</b></span><span style=\"color: rgb(51, 51, 51);\">\u7684\u9009\u624b\u5c06\u6bcf\u4eba\u83b7\u5f97CGX\u8d5e\u52a9\u7684<b>\u53cc\u6c47\u8089\u5757\u738b\u7279\u7ea7\u706b\u817f\u80a0</b></span><span style=\"color: rgb(51, 51, 51);\"><b>\u4e00\u6839</b></span><br /></span></p><p>\u516b\u3001\u6bd4\u8d5b\u7ed3\u675f\u540e\uff0c<b>\u968f\u673a\u62bd\u53d6\u4e09\u540d\u540c\u5b66</b>\u9001<b>\u725b\u5ba2\u886c\u886b</b>\uff0c\u6ee1\u8db3\u4f60\u6c38\u8fdc\u62bd\u4e0d\u5230\u886c\u886b\u7684\u975e\u914b\u7684\u613f\u671b\uff01</p><p><b><u>\u4ee5\u4e0a\u89c4\u5219\u6700\u7ec8\u89e3\u91ca\u6743\u5f52\u521b\u65b0\u5b9e\u9a8c\u5ba4\u6240\u6709</u></b>\u3002</p><h1><font>\u7f5a\u65f6\u89c4\u5219\u548c\u8fd4\u56de\u7ed3\u679c\u89e3\u91ca:</font></h1><p><font>1.\u63d0\u4ea4\u663e\u793aAccepted\u5373\u4e3a\u901a\u8fc7,\u82e5\u663e\u793a\u5176\u4ed6\u7ed3\u679c\u5373\u8868\u793a\u9519\u8bef.\u9519\u8bef\u4e00\u6b21\u603b\u7f5a\u65f6+20\u5206\u949f,\u8bf7\u8c28\u614e\u63d0\u4ea4\uff01</font></p><p><font>2.\u5173\u4e8e\u8fd4\u56de\u7ed3\u679c\u7684\u89e3\u91ca:</font></p><p><font>Pending & Juding : You solution will be judged soon, please wait for result</font></p><p><font>Compile Error : Failed to compile your source code. Click on the link to see compiler&#039;s output.</font></p><p><font>Accepted : Congratulations. Your solution is correct.</font></p><p><font>Wrong Answer : Your program&#039;s output doesn&#039;t match judger&#039;s answer.</font></p><p><font>Runtime Error : Your program terminated abnormally. Possible reasons are: segment fault, divided by zero or exited with code other than 0.OrThe memory your program actually used has exceeded limit.</font></p><p><font>Time Limit Exceeded : The CPU time your program used has exceeded limit. Java has a triple time limit.</font></p><p><font>Memory Limit Exceeded : The memory your program actually used has exceeded limit.</font></p><p><font>System Error : Oops, something has gone wrong with the judger. Please report this to administrator.</font></p><h1><font>\u6bd4\u8d5b\u8981\u6c42:</font></h1><p><font>\u6bd4\u8d5b\u8fc7\u7a0b\u4e2d<b>\u4e0d\u8bb8\u8ba8\u8bba</b>\u4e0d\u8bb8\u4e0a\u5916\u7f51,\u6709\u95ee\u9898\u53ef\u4ee5\u4e3e\u624b!</font></p><p><font><b>\u9898\u76ee\u96be\u5ea6\u4e0e\u9898\u76ee\u987a\u5e8f\u65e0\u5173,\u8bf7\u5408\u7406\u5b89\u6392\u505a\u9898\u65f6\u95f4!</b></font></p>",
},
{
beginTime: "2020-11-08T05:00:00Z",
duration: "5hours",
type: "ACM",
description:"<p>测试</p>"
}
],
};
},
methods: {
goContest() {},
},
filters: {
localtime(value) {
return time.utcToLocal(value);
},
},
};
</script>
<style scoped>
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 200px;
margin: 0;
}
.el-carousel__item:nth-child(n) {
background-color: #fff;
}
.el-carousel__item {
overflow-y: auto!important;
}
.el-col {
margin-top: 25px;
}
.contest {
text-align: center;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
.contest .title .el-link {
font-size: 25px;
font-weight: 500;
color: #444;
}
.clearfix h2 {
color: #409eff;
}
.el-link.el-link--default:hover {
color: #409eff;
transition: all 0.28s ease;
}
.contest .content-info {
padding: 0 70px 40px 70px;
}
.contest .contest-description {
margin-top: 25px;
/* text-align: left; */
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<div>
<el-row :gutter="20">
<el-col :md="12" :sm="24">
<el-card class="container">
<div slot="header"><span class="panel-title home-title">Compiler & Example</span></div>
<div class="content markdown-body">
<ul>
<li v-for="lang in languages" :key="lang.name">
{{ lang.name }} ( {{ lang.description }} )
<p style="color: #409EFF;font-size:16px">Compiler</p>
<pre>{{ lang.compile_command }}</pre>
<p style="color: #409EFF;font-size:16px">A+B Problem</p>
<Highlight
:code="lang.template"
:language="lang.name"
></Highlight>
</li>
</ul>
</div>
</el-card>
</el-col>
<el-col :md="12" :sm="24">
<el-card class="container">
<div slot="header"><span class="panel-title home-title">Result Explanation</span></div>
<ul class="result">
<li>
<span :class="getStatusColor(6)">Pending</span>&<span :class="getStatusColor(7)">Judging</span> : 您的解答将很快被测评请等待结果
</li>
<li>
<span :class="getStatusColor(-2)">Compile Error</span> : 无法编译您的源代码点击链接查看编译器的输出
</li>
<li>
<span :class="getStatusColor(-3)">Presentation Error</span> : 您提交的代码输出格式与评测输出不一致请检查行末是否有多余空格
</li>
<li>
<span :class="getStatusColor(0)">Accepted</span> : 您的解题方法是正确的
</li>
<li>
<span :class="getStatusColor(-1)">Wrong Answer</span> : 您的程序输出结果与判题程序的答案不符
</li>
<li>
<span :class="getStatusColor(4)">Runtime Error</span> : 您的程序异常终止可能的原因是段错误被零除或用非0的代码退出程序
</li>
<li>
<span :class="getStatusColor(2)">Time Limit Exceeded</span> : 您的程序使用的 CPU 时间已超出题目限制
</li>
<li>
<span :class="getStatusColor(3)">Memory Limit Exceeded</span> : 您的程序实际使用的内存已超出题目限制
</li>
<li>
<span :class="getStatusColor(5)">System Error</span> : 糟糕判题机系统出了问题请报告给管理员
</li>
</ul>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import utils from "@/common/utils";
import Highlight from "@/components/common/Highlight";
import { JUDGE_STATUS } from "@/common/constants";
export default {
components: {
Highlight,
},
data() {
return {
languages: [],
JUDGE_STATUS:JUDGE_STATUS
};
},
methods:{
getStatusColor(status) {
return "el-tag el-tag--medium status-" + JUDGE_STATUS[status].color;
},
},
beforeRouteEnter(to, from, next) {
utils.getLanguages().then((languages) => {
next((vm) => {
vm.languages = languages;
});
});
},
};
</script>
<style scoped>
.container {
margin-bottom: 20px;
}
.container .content {
font-size: 16px;
margin: 0 50px 20px 50px;
}
@media screen and (max-width: 768px) {
.container .content {
font-size: 1rem;
margin:0 5px;
}
}
ul {
list-style: disc;
padding-inline-start:0px;
}
li {
line-height: 2;
}
li .title {
font-weight: 500;
}
.result li{
list-style-type:none;
margin-top:8px;
}
</style>

View File

@ -68,11 +68,11 @@
<ol id="contest-list">
<li v-for="contest in contests" :key="contest.title" :style="getborderColor(contest)">
<el-row type="flex" justify="space-between" align="middle">
<el-col :xs="10" :md="2" :lg="2">
<el-col :xs="10" :sm="4" :md="3" :lg="2">
<img v-show="contest.rule_type == 'ACM'" class="trophy" :src="acmSrc" width="95px"/>
<img v-show="contest.rule_type == 'OI'" class="trophy" :src="oiSrc" width="95px" />
</el-col>
<el-col :xs="10" :md="20" :lg="20" class="contest-main">
<el-col :xs="10" :sm="16" :md="19" :lg="20" class="contest-main">
<p class="title">
<a class="entry" @click.stop="toContest(contest)">
{{ contest.title }}
@ -118,7 +118,7 @@
</li>
</ul>
</el-col>
<el-col :xs="4" :md="2" :lg="2" style="text-align: center">
<el-col :xs="4" :sm="4" :md="2" :lg="2" style="text-align: center">
<el-tag
effect="dark"
:color="CONTEST_STATUS_REVERSE[contest.status].color"
@ -318,12 +318,22 @@ export default {
.filter-row span {
margin-right: 2px;
}
ol{
padding-inline-start: 5px;
}
/deep/ .el-card__header {
margin-bottom: 5px;
}
}
@media screen and (min-width: 768px) {
.filter-row span {
margin-right: 20px;
}
}
/deep/ .el-card__header {
border-bottom: 0px;
}
#contest-list > li {
padding: 5px;
margin-left: -20px;

View File

@ -37,7 +37,7 @@
>
</template>
</vxe-table-column>
<vxe-table-column field="status" title="Status" min-width="100">
<vxe-table-column field="status" title="Status" min-width="170">
<template v-slot="{ row }">
<span :class="getStatusColor(row.status)">{{
JUDGE_STATUS[row.status].name

View File

@ -93,7 +93,7 @@
>
</template>
</vxe-table-column>
<vxe-table-column field="status" title="Status" min-width="100">
<vxe-table-column field="status" title="Status" min-width="170">
<template v-slot="{ row }">
<span :class="getStatusColor(row.status)">{{
JUDGE_STATUS[row.status].name
@ -172,7 +172,7 @@ export default {
sid: 1000,
stime: "2020-08-08 16:00:00",
pid: "1001",
status: 0,
status: 1,
time: "4ms",
memory: "3MB",
language: "C++",
@ -183,7 +183,7 @@ export default {
sid: 1001,
stime: "2020-08-08 16:00:00",
pid: "1001",
status: 0,
status: -3,
time: "1000ms",
memory: "3MB",
language: "C++",
@ -194,7 +194,7 @@ export default {
sid: 1000,
stime: "2020-08-08 16:00:00",
pid: "1001",
status: 0,
status: 3,
time: "4ms",
memory: "3MB",
language: "C++",