mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 08:23:20 +00:00
Accept Merge Request #281 后台部分重构,还未完成;部分代码修改为 web 组件;修复部分小 bug;更新个人主页样式 : (virusdefender-dev -> dev)
Merge Request: 后台部分重构,还未完成;部分代码修改为 web 组件;修复部分小 bug;更新个人主页样式 Created By: @virusdefender Accepted By: @virusdefender URL: https://coding.net/u/virusdefender/p/qduoj/git/merge/281
This commit is contained in:
commit
a176999750
@ -1,4 +1,5 @@
|
||||
# coding=utf-8
|
||||
import urllib
|
||||
import functools
|
||||
from functools import wraps
|
||||
|
||||
@ -27,7 +28,7 @@ class BasePermissionDecorator(object):
|
||||
if self.request.is_ajax():
|
||||
return error_response(u"请先登录")
|
||||
else:
|
||||
return HttpResponseRedirect("/login/")
|
||||
return HttpResponseRedirect("/login/?__from=" + urllib.quote(self.request.build_absolute_uri()))
|
||||
|
||||
def check_permission(self):
|
||||
raise NotImplementedError()
|
||||
|
37
account/migrations/0013_userprofile.py
Normal file
37
account/migrations/0013_userprofile.py
Normal file
@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import jsonfield.fields
|
||||
import account.models
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('account', '0012_auto_20151012_1546'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserProfile',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('avatar', models.CharField(default=account.models._random_avatar, max_length=50)),
|
||||
('blog', models.URLField(null=True, blank=True)),
|
||||
('mood', models.CharField(max_length=200, null=True, blank=True)),
|
||||
('hduoj_username', models.CharField(max_length=30, null=True, blank=True)),
|
||||
('bestcoder_username', models.CharField(max_length=30, null=True, blank=True)),
|
||||
('codeforces_username', models.CharField(max_length=30, null=True, blank=True)),
|
||||
('rank', models.IntegerField(default=65535)),
|
||||
('accepted_number', models.IntegerField(default=0)),
|
||||
('submissions_number', models.IntegerField(default=0)),
|
||||
('problems_status', jsonfield.fields.JSONField(default={})),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'user_profile',
|
||||
},
|
||||
),
|
||||
]
|
@ -48,3 +48,26 @@ class User(AbstractBaseUser):
|
||||
|
||||
class Meta:
|
||||
db_table = "user"
|
||||
|
||||
|
||||
def _random_avatar():
|
||||
import random
|
||||
return "/static/img/avatar/avatar-" + str(random.randint(1, 20)) + ".png"
|
||||
|
||||
|
||||
class UserProfile(models.Model):
|
||||
user = models.OneToOneField(User)
|
||||
avatar = models.CharField(max_length=50, default=_random_avatar)
|
||||
blog = models.URLField(blank=True, null=True)
|
||||
mood = models.CharField(max_length=200, blank=True, null=True)
|
||||
hduoj_username = models.CharField(max_length=30, blank=True, null=True)
|
||||
bestcoder_username = models.CharField(max_length=30, blank=True, null=True)
|
||||
codeforces_username = models.CharField(max_length=30, blank=True, null=True)
|
||||
rank = models.IntegerField(default=65535)
|
||||
accepted_number = models.IntegerField(default=0)
|
||||
submissions_number = models.IntegerField(default=0)
|
||||
# JSON字典用来表示该用户的问题的解决状态 1为ac,2为正在进行
|
||||
problems_status = JSONField(default={})
|
||||
|
||||
class Meta:
|
||||
db_table = "user_profile"
|
||||
|
@ -57,4 +57,8 @@ class ApplyResetPasswordSerializer(serializers.Serializer):
|
||||
class ResetPasswordSerializer(serializers.Serializer):
|
||||
token = serializers.CharField(min_length=1, max_length=40)
|
||||
password = serializers.CharField(min_length=6, max_length=30)
|
||||
captcha = serializers.CharField(max_length=4, min_length=4)
|
||||
captcha = serializers.CharField(max_length=4, min_length=4)
|
||||
|
||||
|
||||
class SSOSerializer(serializers.Serializer):
|
||||
token = serializers.CharField(max_length=40)
|
@ -5,6 +5,7 @@ from django.contrib import auth
|
||||
from django.shortcuts import render
|
||||
from django.db.models import Q
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.core.exceptions import MultipleObjectsReturned
|
||||
from django.utils.timezone import now
|
||||
|
||||
@ -20,7 +21,8 @@ from .models import User
|
||||
from .serializers import (UserLoginSerializer, UsernameCheckSerializer,
|
||||
UserRegisterSerializer, UserChangePasswordSerializer,
|
||||
EmailCheckSerializer, UserSerializer, EditUserSerializer,
|
||||
ApplyResetPasswordSerializer, ResetPasswordSerializer)
|
||||
ApplyResetPasswordSerializer, ResetPasswordSerializer,
|
||||
SSOSerializer)
|
||||
from .decorators import super_admin_required
|
||||
|
||||
|
||||
@ -284,15 +286,37 @@ class ResetPasswordAPIView(APIView):
|
||||
|
||||
|
||||
def user_index_page(request, username):
|
||||
return render(request, "oj/account/user_index.html")
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
return error_page(request, u"用户不存在")
|
||||
|
||||
blog_link = ""
|
||||
|
||||
if user.userprofile.blog:
|
||||
blog_link = user.userprofile.blog.replace("http://", "").replace("https://", "")
|
||||
|
||||
return render(request, "oj/account/user_index.html", {"user": user, "blog_link": blog_link})
|
||||
|
||||
|
||||
def auth_page(request):
|
||||
if not request.user.is_authenticated():
|
||||
return render(request, "oj/account/oauth.html")
|
||||
callback = request.GET.get("callback", None)
|
||||
if not callback:
|
||||
return error_page(request, u"参数错误")
|
||||
token = rand_str()
|
||||
request.user.auth_token = token
|
||||
return render(request, "oj/account/oauth.html", {"callback": callback, "token": token})
|
||||
class SSOAPIView(APIView):
|
||||
def post(self, request):
|
||||
serializer = SSOSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
try:
|
||||
user = User.objects.get(auth_token=serializer.data["token"])
|
||||
return success_response({"username": user.username})
|
||||
except User.DoesNotExist:
|
||||
return error_response(u"用户不存在")
|
||||
else:
|
||||
return serializer_invalid_response(serializer)
|
||||
|
||||
@login_required
|
||||
def get(self, request):
|
||||
callback = request.GET.get("callback", None)
|
||||
if not callback or callback != settings.SSO["callback"]:
|
||||
return error_page(request, u"参数错误")
|
||||
token = rand_str()
|
||||
request.user.auth_token = token
|
||||
request.user.save()
|
||||
return render(request, "oj/account/sso.html", {"redirect_url": callback + "?token=" + token, "callback": callback})
|
@ -1,4 +1,5 @@
|
||||
# coding=utf-8
|
||||
import urllib
|
||||
from functools import wraps
|
||||
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
@ -30,7 +31,7 @@ def check_user_contest_permission(func):
|
||||
if request.is_ajax():
|
||||
return error_response(u"请先登录")
|
||||
else:
|
||||
return HttpResponseRedirect("/login/")
|
||||
return HttpResponseRedirect("/login/?__from=" + urllib.quote(request.build_absolute_uri()))
|
||||
|
||||
# kwargs 就包含了 url 里面的参数
|
||||
if "contest_id" in kwargs:
|
||||
|
@ -11,10 +11,8 @@ from .models import Contest, ContestProblem
|
||||
class CreateContestSerializer(serializers.Serializer):
|
||||
title = serializers.CharField(max_length=40)
|
||||
description = serializers.CharField(max_length=5000)
|
||||
mode = serializers.IntegerField()
|
||||
contest_type = serializers.IntegerField()
|
||||
real_time_rank = serializers.BooleanField()
|
||||
show_user_submission = serializers.BooleanField()
|
||||
password = serializers.CharField(max_length=30, required=False, default=None)
|
||||
start_time = serializers.DateTimeField()
|
||||
end_time = serializers.DateTimeField()
|
||||
@ -45,10 +43,8 @@ class EditContestSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
title = serializers.CharField(max_length=40)
|
||||
description = serializers.CharField(max_length=10000)
|
||||
mode = serializers.IntegerField()
|
||||
contest_type = serializers.IntegerField()
|
||||
real_time_rank = serializers.BooleanField()
|
||||
show_user_submission = serializers.BooleanField()
|
||||
password = serializers.CharField(max_length=30, required=False, default=None)
|
||||
start_time = serializers.DateTimeField()
|
||||
end_time = serializers.DateTimeField()
|
||||
|
@ -1,9 +0,0 @@
|
||||
# coding=utf-8
|
||||
from django.conf.urls import include, url
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
url(r'^login/$', TemplateView.as_view(template_name="oj/account/login.html"), name="user_login_page"),
|
||||
]
|
@ -64,9 +64,8 @@ class ContestAdminAPIView(APIView):
|
||||
return error_response(u"比赛的开始时间必须早于比赛结束的时间")
|
||||
try:
|
||||
contest = Contest.objects.create(title=data["title"], description=data["description"],
|
||||
mode=data["mode"], contest_type=data["contest_type"],
|
||||
contest_type=data["contest_type"],
|
||||
real_time_rank=data["real_time_rank"], password=data["password"],
|
||||
show_user_submission=data["show_user_submission"],
|
||||
start_time=dateparse.parse_datetime(data["start_time"]),
|
||||
end_time=dateparse.parse_datetime(data["end_time"]),
|
||||
created_by=request.user, visible=data["visible"])
|
||||
@ -125,10 +124,8 @@ class ContestAdminAPIView(APIView):
|
||||
|
||||
contest.title = data["title"]
|
||||
contest.description = data["description"]
|
||||
contest.mode = data["mode"]
|
||||
contest.contest_type = data["contest_type"]
|
||||
contest.real_time_rank = data["real_time_rank"]
|
||||
contest.show_user_submission = data["show_user_submission"]
|
||||
contest.start_time = dateparse.parse_datetime(data["start_time"])
|
||||
contest.end_time = dateparse.parse_datetime(data["end_time"])
|
||||
contest.visible = data["visible"]
|
||||
@ -225,6 +222,7 @@ class ContestProblemAdminAPIView(APIView):
|
||||
contest_problem.visible = data["visible"]
|
||||
contest_problem.sort_index = data["sort_index"]
|
||||
contest_problem.score = data["score"]
|
||||
contest_problem.last_update_time = now()
|
||||
contest_problem.save()
|
||||
return success_response(ContestProblemSerializer(contest_problem).data)
|
||||
else:
|
||||
@ -486,6 +484,10 @@ def contest_problem_submissions_list_page(request, contest_id, page=1):
|
||||
if user_id:
|
||||
submissions = submissions.filter(user_id=request.GET.get("user_id"))
|
||||
|
||||
problem_id = request.GET.get("problem_id", None)
|
||||
if problem_id:
|
||||
submissions = submissions.filter(problem_id=problem_id)
|
||||
|
||||
# 封榜的时候只能看到自己的提交
|
||||
if not contest.real_time_rank:
|
||||
if not (request.user.admin_type == SUPER_ADMIN or request.user == contest.created_by):
|
||||
@ -535,4 +537,4 @@ def contest_problem_submissions_list_page(request, contest_id, page=1):
|
||||
return render(request, "oj/contest/submissions_list.html",
|
||||
{"submissions": current_page, "page": int(page),
|
||||
"previous_page": previous_page, "next_page": next_page, "start_id": int(page) * 20 - 20,
|
||||
"contest": contest, "filter": filter, "user_id": user_id})
|
||||
"contest": contest, "filter": filter, "user_id": user_id, "problem_id": problem_id})
|
@ -11,18 +11,13 @@ DATABASES = {
|
||||
},
|
||||
# submission 的 name 和 engine 请勿修改,其他代码会用到
|
||||
'submission': {
|
||||
'NAME': 'oj_submission',
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'CONN_MAX_AGE': 0.1,
|
||||
'HOST': "127.0.0.1",
|
||||
'PORT': 3306,
|
||||
'USER': 'root',
|
||||
'PASSWORD': 'root',
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db1.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
REDIS_CACHE = {
|
||||
"host": "121.42.32.129",
|
||||
"host": "127.0.0.1",
|
||||
"port": 6379,
|
||||
"db": 1
|
||||
}
|
||||
@ -36,4 +31,6 @@ ALLOWED_HOSTS = []
|
||||
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static/src/"), BASE_DIR]
|
||||
|
||||
# 模板文件夹
|
||||
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'template/src/')]
|
||||
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'template/src/')]
|
||||
|
||||
SSO = {"callback": "http://localhost:8765/login"}
|
@ -43,3 +43,5 @@ STATICFILES_DIRS = [os.path.join(BASE_DIR, "static/release/"), os.path.join(BASE
|
||||
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'template/release/')]
|
||||
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
|
||||
SSO = {"callback": "https://discuss.acmer.site/login"}
|
||||
|
@ -6,7 +6,7 @@ from django.views.generic import TemplateView
|
||||
from account.views import (UserLoginAPIView, UsernameCheckAPIView, UserRegisterAPIView,
|
||||
UserChangePasswordAPIView, EmailCheckAPIView,
|
||||
UserAdminAPIView, UserInfoAPIView,
|
||||
ApplyResetPasswordAPIView)
|
||||
ApplyResetPasswordAPIView, SSOAPIView)
|
||||
|
||||
from announcement.views import AnnouncementAdminAPIView
|
||||
|
||||
@ -121,13 +121,13 @@ urlpatterns = [
|
||||
url(r'^api/contest/time/$', ContestTimeAPIView.as_view(), name="contest_time_api_view"),
|
||||
url(r'^api/admin/rejudge/$', SubmissionRejudgeAdminAPIView.as_view(), name="submission_rejudge_api"),
|
||||
|
||||
url(r'^user/(?P<username>\w+)/$', "account.views.user_index_page"),
|
||||
url(r'^user/(?P<username>.+)/$', "account.views.user_index_page"),
|
||||
|
||||
url(r'^api/reset_password/$', ApplyResetPasswordAPIView.as_view(), name="apply_reset_password_api"),
|
||||
|
||||
url(r'^account/settings/$', TemplateView.as_view(template_name="oj/account/settings.html"), name="account_setting_page"),
|
||||
url(r'^account/settings/avatar/$', TemplateView.as_view(template_name="oj/account/avatar.html"), name="avatar_settings_page"),
|
||||
url(r'^account/auth/$', "account.views.auth_page", name="auth_login_page"),
|
||||
url(r'^account/sso/$', SSOAPIView.as_view(), name="sso_api"),
|
||||
]
|
||||
|
||||
|
||||
|
@ -62,3 +62,32 @@ pre, code {
|
||||
font-family: "source_code_pro";
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#index-avatar{
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#user-mood{
|
||||
max-width: 70%;
|
||||
}
|
||||
|
||||
#oj-logo{
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.super-admin-star{
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
.admin-star{
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#user-data-number{
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#user-data-text{
|
||||
display: block;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "datetimePicker",
|
||||
"validator"],
|
||||
"validator", "editorComponent"],
|
||||
function ($, avalon, editor, uploader, bsAlert, csrfTokenHeader) {
|
||||
|
||||
$("#add-contest-form").validator().on('submit', function (e) {
|
||||
@ -7,11 +7,9 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "date
|
||||
e.preventDefault();
|
||||
var ajaxData = {
|
||||
title: vm.title,
|
||||
description: vm.description,
|
||||
mode: vm.mode,
|
||||
description: avalon.vmodels.contestDescriptionEditor.content,
|
||||
contest_type: 0,
|
||||
real_time_rank: vm.realTimeRank,
|
||||
show_user_submission: vm.showSubmission,
|
||||
start_time: vm.startTime,
|
||||
end_time: vm.endTime,
|
||||
visible: false
|
||||
@ -38,12 +36,11 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "date
|
||||
bsAlert("你没有选择参赛用户!");
|
||||
return false;
|
||||
}
|
||||
if (vm.editDescription == "") {
|
||||
if (ajaxData.description.trim() == "") {
|
||||
bsAlert("比赛描述不能为空!");
|
||||
return false;
|
||||
}
|
||||
$.ajax({ // Add contest
|
||||
beforeSend: csrfTokenHeader,
|
||||
$.ajax({
|
||||
url: "/api/admin/contest/",
|
||||
dataType: "json",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
@ -52,17 +49,7 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "date
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
bsAlert("添加成功!将转到比赛列表页以便为比赛添加问题(注意比赛当前状态为:隐藏)");
|
||||
vm.title = "";
|
||||
vm.description = "";
|
||||
vm.startTime = "";
|
||||
vm.endTime = "";
|
||||
vm.password = "";
|
||||
vm.mode = "0";
|
||||
vm.showSubmission = true;
|
||||
location.hash = "#contest/contest_list";
|
||||
vm.isGlobal = true;
|
||||
vm.allGroups = [];
|
||||
vm.showGlobalViewRadio = true;
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
@ -73,23 +60,25 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "date
|
||||
return false;
|
||||
});
|
||||
|
||||
editor("#editor");
|
||||
//editor("#editor");
|
||||
if (avalon.vmodels.add_contest)
|
||||
var vm = avalon.vmodels.add_contest;
|
||||
else
|
||||
var vm = avalon.define({
|
||||
$id: "add_contest",
|
||||
title: "",
|
||||
description: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
password: "",
|
||||
mode: "0",
|
||||
showSubmission: true,
|
||||
isGlobal: true,
|
||||
allGroups: [],
|
||||
showGlobalViewRadio: true,
|
||||
realTimeRank: true
|
||||
realTimeRank: true,
|
||||
|
||||
contestDescriptionEditor: {
|
||||
editorId: "contest-description-editor",
|
||||
placeholder: "比赛介绍内容"
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
@ -102,7 +91,6 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "date
|
||||
if (data.data.admin_type == 1) {
|
||||
vm.isGlobal = false;
|
||||
vm.showGlobalViewRadio = false;
|
||||
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
|
@ -1,277 +1,38 @@
|
||||
require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker", "validator"], function ($, avalon, csrfTokenHeader, bsAlert, editor) {
|
||||
require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker", "validator", "pager"], function ($, avalon, csrfTokenHeader, bsAlert, editor) {
|
||||
|
||||
avalon.ready(function () {
|
||||
|
||||
$("#edit-contest-form").validator().on('submit', function (e) {
|
||||
if (!e.isDefaultPrevented()) {
|
||||
e.preventDefault();
|
||||
var ajaxData = {
|
||||
id: vm.contestList[vm.editingContestId - 1].id,
|
||||
title: vm.editTitle,
|
||||
description: vm.editDescription,
|
||||
mode: vm.editMode,
|
||||
contest_type: 0,
|
||||
real_time_rank: vm.editRealTimeRank,
|
||||
show_user_submission: vm.editShowSubmission,
|
||||
start_time: vm.editStartTime,
|
||||
end_time: vm.editEndTime,
|
||||
visible: vm.editVisible
|
||||
};
|
||||
|
||||
var selectedGroups = [];
|
||||
if (!vm.isGlobal) {
|
||||
for (var i = 0; i < vm.allGroups.length; i++) {
|
||||
if (vm.allGroups[i].isSelected) {
|
||||
selectedGroups.push(vm.allGroups[i].id);
|
||||
}
|
||||
}
|
||||
ajaxData.groups = selectedGroups;
|
||||
}
|
||||
else {
|
||||
if (vm.editPassword) {
|
||||
ajaxData.password = vm.editPassword;
|
||||
ajaxData.contest_type = 2;
|
||||
}
|
||||
else
|
||||
ajaxData.contest_type = 1;
|
||||
}
|
||||
if (!vm.isGlobal && !selectedGroups.length) {
|
||||
bsAlert("你没有选择参赛用户!");
|
||||
return false;
|
||||
}
|
||||
if (vm.editDescription == "") {
|
||||
bsAlert("比赛描述不能为空!");
|
||||
return false;
|
||||
}
|
||||
|
||||
$.ajax({ // modify contest info
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/contest/",
|
||||
dataType: "json",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
data: JSON.stringify(ajaxData),
|
||||
method: "put",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
bsAlert("修改成功!");
|
||||
vm.editingContestId = 0; // Hide the editor
|
||||
vm.getPage(1); // Refresh the contest list
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (avalon.vmodels.contestList) {
|
||||
// this page has been loaded before, so set the default value
|
||||
var vm = avalon.vmodels.contestList;
|
||||
vm.contestList = [];
|
||||
vm.previousPage = 0;
|
||||
vm.nextPage = 0;
|
||||
vm.page = 1;
|
||||
vm.totalPage = 1;
|
||||
vm.keyword = "";
|
||||
vm.editingContestId = 0;
|
||||
vm.editTitle = "";
|
||||
vm.editDescription = "";
|
||||
vm.editProblemList = [];
|
||||
vm.editPassword = "";
|
||||
vm.editStartTime = "";
|
||||
vm.editEndTime = "";
|
||||
vm.editMode = "";
|
||||
vm.editShowSubmission = false;
|
||||
vm.editVisible = false;
|
||||
vm.editingProblemContestIndex = 0;
|
||||
vm.editRealTimeRank = true;
|
||||
}
|
||||
else {
|
||||
var vm = avalon.define({
|
||||
$id: "contestList",
|
||||
contestList: [],
|
||||
previousPage: 0,
|
||||
nextPage: 0,
|
||||
page: 1,
|
||||
totalPage: 1,
|
||||
showVisibleOnly: false,
|
||||
keyword: "",
|
||||
editingContestId: 0,
|
||||
editTitle: "",
|
||||
editDescription: "",
|
||||
editProblemList: [],
|
||||
editPassword: "",
|
||||
editStartTime: "",
|
||||
editEndTime: "",
|
||||
editMode: "",
|
||||
editShowSubmission: false,
|
||||
editVisible: false,
|
||||
editRealTimeRank: true,
|
||||
editingProblemContestIndex: 0,
|
||||
isGlobal: true,
|
||||
allGroups: [],
|
||||
showGlobalViewRadio: true,
|
||||
admin_type: 1,
|
||||
getNext: function () {
|
||||
if (!vm.nextPage)
|
||||
return;
|
||||
getPageData(vm.page + 1);
|
||||
},
|
||||
getPrevious: function () {
|
||||
if (!vm.previousPage)
|
||||
return;
|
||||
getPageData(vm.page - 1);
|
||||
},
|
||||
getBtnClass: function (btn) {
|
||||
if (btn == "next") {
|
||||
return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||
}
|
||||
else {
|
||||
return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||
showVisibleOnly: false,
|
||||
pager: {
|
||||
getPage: function(page){
|
||||
getPage(page);
|
||||
}
|
||||
},
|
||||
getPage: function (page_index) {
|
||||
getPageData(page_index);
|
||||
},
|
||||
showEditContestArea: function (contestId) {
|
||||
if (vm.editingContestId && !confirm("如果继续将丢失未保存的信息,是否继续?"))
|
||||
return;
|
||||
if (contestId == vm.editingContestId)
|
||||
vm.editingContestId = 0;
|
||||
else {
|
||||
vm.editingContestId = contestId;
|
||||
vm.editTitle = vm.contestList[contestId - 1].title;
|
||||
vm.editPassword = vm.contestList[contestId - 1].password;
|
||||
vm.editStartTime = vm.contestList[contestId - 1].start_time.substring(0, 16).replace("T", " ");
|
||||
vm.editEndTime = vm.contestList[contestId - 1].end_time.substring(0, 16).replace("T", " ");
|
||||
vm.editMode = vm.contestList[contestId - 1].mode;
|
||||
vm.editVisible = vm.contestList[contestId - 1].visible;
|
||||
vm.editRealTimeRank = vm.contestList[contestId - 1].real_time_rank;
|
||||
if (vm.contestList[contestId - 1].contest_type == 0) { //contest type == 0, contest in group
|
||||
vm.isGlobal = false;
|
||||
for (var i = 0; i < vm.allGroups.length; i++) {
|
||||
vm.allGroups[i].isSelected = false;
|
||||
}
|
||||
for (var i = 0; i < vm.contestList[contestId - 1].groups.length; i++) {
|
||||
var id = parseInt(vm.contestList[contestId - 1].groups[i]);
|
||||
|
||||
for (var index = 0; vm.allGroups[index]; index++) {
|
||||
if (vm.allGroups[index].id == id) {
|
||||
vm.allGroups[index].isSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
vm.isGlobal = true;
|
||||
}
|
||||
vm.editShowSubmission = vm.contestList[contestId - 1].show_user_submission;
|
||||
editor("#editor").setValue(vm.contestList[contestId - 1].description);
|
||||
vm.editingProblemContestIndex = 0;
|
||||
}
|
||||
},
|
||||
showEditProblemArea: function (contestId) {
|
||||
if (vm.editingProblemContestIndex == contestId) {
|
||||
vm.editingProblemContestIndex = 0;
|
||||
return;
|
||||
}
|
||||
if (vm.editingContestId && !confirm("如果继续将丢失未保存的信息,是否继续?")) {
|
||||
return;
|
||||
}
|
||||
$.ajax({ // Get the problem list of current contest
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/contest_problem/?contest_id=" + vm.contestList[contestId - 1].id,
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
vm.editProblemList = data.data;
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
vm.editingContestId = 0;
|
||||
vm.editingProblemContestIndex = contestId;
|
||||
vm.editMode = vm.contestList[contestId - 1].mode;
|
||||
},
|
||||
addProblem: function () {
|
||||
vm.$fire("up!showContestProblemPage", 0, vm.contestList[vm.editingProblemContestIndex - 1].id, vm.editMode);
|
||||
},
|
||||
showProblemEditPage: function (el) {
|
||||
vm.$fire("up!showContestProblemPage", el.id, vm.contestList[vm.editingProblemContestIndex - 1].id, vm.editMode);
|
||||
},
|
||||
showSubmissionPage: function (el) {
|
||||
var problemId = 0
|
||||
if (el)
|
||||
problemId = el.id;
|
||||
vm.$fire("up!showContestSubmissionPage", problemId, vm.contestList[vm.editingProblemContestIndex - 1].id, vm.editMode);
|
||||
},
|
||||
addToProblemList: function (problem) {
|
||||
var ajaxData = {
|
||||
title: problem.title,
|
||||
description: problem.description,
|
||||
time_limit: problem.time_limit,
|
||||
memory_limit: problem.memory_limit,
|
||||
samples: [],
|
||||
test_case_id: problem.test_case_id,
|
||||
hint: problem.hint,
|
||||
source: problem.contest.title,
|
||||
visible: false,
|
||||
tags: [],
|
||||
input_description: problem.input_description,
|
||||
output_description: problem.output_description,
|
||||
difficulty: 0
|
||||
};
|
||||
for (var i = 0; i < problem.samples.length; i++) {
|
||||
ajaxData.samples.push({input: problem.samples[i].input, output: problem.samples[i].output})
|
||||
}
|
||||
$.ajax({
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/problem/",
|
||||
dataType: "json",
|
||||
data: JSON.stringify(ajaxData),
|
||||
method: "post",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
bsAlert("题目添加成功!题目现在处于隐藏状态,请到题目列表手动修改,并添加分类和难度信息!");
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
search: function () {
|
||||
getPage(1);
|
||||
avalon.vmodels.contestListPager.currentPage = 1;
|
||||
}
|
||||
});
|
||||
vm.$watch("showVisibleOnly", function () {
|
||||
getPageData(1);
|
||||
})
|
||||
}
|
||||
getPageData(1);
|
||||
|
||||
//init time picker
|
||||
$("#contest_start_time").datetimepicker({
|
||||
format: "yyyy-mm-dd hh:ii",
|
||||
minuteStep: 5,
|
||||
weekStart: 1,
|
||||
language: "zh-CN"
|
||||
});
|
||||
$("#contest_end_time").datetimepicker({
|
||||
format: "yyyy-mm-dd hh:ii",
|
||||
minuteStep: 5,
|
||||
weekStart: 1,
|
||||
language: "zh-CN"
|
||||
vm.$watch("showVisibleOnly", function () {
|
||||
getPage(1);
|
||||
avalon.vmodels.contestListPager.currentPage = 1;
|
||||
});
|
||||
|
||||
function getPageData(page) {
|
||||
var url = "/api/admin/contest/?paging=true&page=" + page + "&page_size=10";
|
||||
function getPage(page) {
|
||||
var url = "/api/admin/contest/?paging=true&page=" + page + "&page_size=20";
|
||||
if (vm.showVisibleOnly)
|
||||
url += "&visible=true"
|
||||
url += "&visible=true";
|
||||
if (vm.keyword != "")
|
||||
url += "&keyword=" + vm.keyword;
|
||||
$.ajax({
|
||||
@ -281,10 +42,8 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
vm.contestList = data.data.results;
|
||||
vm.totalPage = data.data.total_page;
|
||||
vm.previousPage = data.data.previous_page;
|
||||
vm.nextPage = data.data.next_page;
|
||||
vm.page = page;
|
||||
vm.announcementList = data.data.results;
|
||||
avalon.vmodels.contestListPager.totalPage = data.data.total_page;
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
@ -293,46 +52,6 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
||||
});
|
||||
}
|
||||
|
||||
// Get group list
|
||||
$.ajax({
|
||||
url: "/api/user/",
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
var admin_type = data.data.admin_type;
|
||||
vm.admin_type = admin_type;
|
||||
if (data.data.admin_type == 1) {
|
||||
vm.isGlobal = false;
|
||||
vm.showGlobalViewRadio = false;
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
url: "/api/admin/group/",
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
if (!data.data.length) {
|
||||
|
||||
if (admin_type != 2)
|
||||
bsAlert("您的用户权限只能创建小组内比赛,但是您还没有创建过小组");
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < data.data.length; i++) {
|
||||
var item = data.data[i];
|
||||
item["isSelected"] = false;
|
||||
vm.allGroups.push(item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
avalon.scan();
|
||||
});
|
321
static/src/js/app/admin/contest/contestList1.js
Normal file
321
static/src/js/app/admin/contest/contestList1.js
Normal file
@ -0,0 +1,321 @@
|
||||
require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker", "validator"], function ($, avalon, csrfTokenHeader, bsAlert, editor) {
|
||||
|
||||
avalon.ready(function () {
|
||||
|
||||
$("#edit-contest-form").validator().on('submit', function (e) {
|
||||
if (!e.isDefaultPrevented()) {
|
||||
e.preventDefault();
|
||||
var ajaxData = {
|
||||
id: vm.contestList[vm.editingContestId - 1].id,
|
||||
title: vm.editTitle,
|
||||
description: vm.editDescription,
|
||||
mode: vm.editMode,
|
||||
contest_type: 0,
|
||||
real_time_rank: vm.editRealTimeRank,
|
||||
show_user_submission: vm.editShowSubmission,
|
||||
start_time: vm.editStartTime,
|
||||
end_time: vm.editEndTime,
|
||||
visible: vm.editVisible
|
||||
};
|
||||
|
||||
var selectedGroups = [];
|
||||
if (!vm.isGlobal) {
|
||||
for (var i = 0; i < vm.allGroups.length; i++) {
|
||||
if (vm.allGroups[i].isSelected) {
|
||||
selectedGroups.push(vm.allGroups[i].id);
|
||||
}
|
||||
}
|
||||
ajaxData.groups = selectedGroups;
|
||||
}
|
||||
else {
|
||||
if (vm.editPassword) {
|
||||
ajaxData.password = vm.editPassword;
|
||||
ajaxData.contest_type = 2;
|
||||
}
|
||||
else
|
||||
ajaxData.contest_type = 1;
|
||||
}
|
||||
if (!vm.isGlobal && !selectedGroups.length) {
|
||||
bsAlert("你没有选择参赛用户!");
|
||||
return false;
|
||||
}
|
||||
if (vm.editDescription == "") {
|
||||
bsAlert("比赛描述不能为空!");
|
||||
return false;
|
||||
}
|
||||
|
||||
$.ajax({ // modify contest info
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/contest/",
|
||||
dataType: "json",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
data: JSON.stringify(ajaxData),
|
||||
method: "put",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
bsAlert("修改成功!");
|
||||
vm.editingContestId = 0; // Hide the editor
|
||||
vm.getPage(1); // Refresh the contest list
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (avalon.vmodels.contestList) {
|
||||
// this page has been loaded before, so set the default value
|
||||
var vm = avalon.vmodels.contestList;
|
||||
vm.contestList = [];
|
||||
}
|
||||
else {
|
||||
var vm = avalon.define({
|
||||
$id: "contestList",
|
||||
contestList: [],
|
||||
previousPage: 0,
|
||||
nextPage: 0,
|
||||
page: 1,
|
||||
totalPage: 1,
|
||||
showVisibleOnly: false,
|
||||
keyword: "",
|
||||
editingContestId: 0,
|
||||
editTitle: "",
|
||||
editDescription: "",
|
||||
editProblemList: [],
|
||||
editPassword: "",
|
||||
editStartTime: "",
|
||||
editEndTime: "",
|
||||
editMode: "",
|
||||
editShowSubmission: false,
|
||||
editVisible: false,
|
||||
editRealTimeRank: true,
|
||||
editingProblemContestIndex: 0,
|
||||
isGlobal: true,
|
||||
allGroups: [],
|
||||
showGlobalViewRadio: true,
|
||||
admin_type: 1,
|
||||
getNext: function () {
|
||||
if (!vm.nextPage)
|
||||
return;
|
||||
getPageData(vm.page + 1);
|
||||
},
|
||||
getPrevious: function () {
|
||||
if (!vm.previousPage)
|
||||
return;
|
||||
getPageData(vm.page - 1);
|
||||
},
|
||||
getBtnClass: function (btn) {
|
||||
if (btn == "next") {
|
||||
return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||
}
|
||||
else {
|
||||
return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||
}
|
||||
},
|
||||
getPage: function (page_index) {
|
||||
getPageData(page_index);
|
||||
},
|
||||
showEditContestArea: function (contestId) {
|
||||
if (vm.editingContestId && !confirm("如果继续将丢失未保存的信息,是否继续?"))
|
||||
return;
|
||||
if (contestId == vm.editingContestId)
|
||||
vm.editingContestId = 0;
|
||||
else {
|
||||
vm.editingContestId = contestId;
|
||||
vm.editTitle = vm.contestList[contestId - 1].title;
|
||||
vm.editPassword = vm.contestList[contestId - 1].password;
|
||||
vm.editStartTime = vm.contestList[contestId - 1].start_time.substring(0, 16).replace("T", " ");
|
||||
vm.editEndTime = vm.contestList[contestId - 1].end_time.substring(0, 16).replace("T", " ");
|
||||
vm.editMode = vm.contestList[contestId - 1].mode;
|
||||
vm.editVisible = vm.contestList[contestId - 1].visible;
|
||||
vm.editRealTimeRank = vm.contestList[contestId - 1].real_time_rank;
|
||||
if (vm.contestList[contestId - 1].contest_type == 0) { //contest type == 0, contest in group
|
||||
vm.isGlobal = false;
|
||||
for (var i = 0; i < vm.allGroups.length; i++) {
|
||||
vm.allGroups[i].isSelected = false;
|
||||
}
|
||||
for (var i = 0; i < vm.contestList[contestId - 1].groups.length; i++) {
|
||||
var id = parseInt(vm.contestList[contestId - 1].groups[i]);
|
||||
|
||||
for (var index = 0; vm.allGroups[index]; index++) {
|
||||
if (vm.allGroups[index].id == id) {
|
||||
vm.allGroups[index].isSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
vm.isGlobal = true;
|
||||
}
|
||||
vm.editShowSubmission = vm.contestList[contestId - 1].show_user_submission;
|
||||
editor("#editor").setValue(vm.contestList[contestId - 1].description);
|
||||
vm.editingProblemContestIndex = 0;
|
||||
}
|
||||
},
|
||||
showEditProblemArea: function (contestId) {
|
||||
if (vm.editingProblemContestIndex == contestId) {
|
||||
vm.editingProblemContestIndex = 0;
|
||||
return;
|
||||
}
|
||||
if (vm.editingContestId && !confirm("如果继续将丢失未保存的信息,是否继续?")) {
|
||||
return;
|
||||
}
|
||||
$.ajax({ // Get the problem list of current contest
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/contest_problem/?contest_id=" + vm.contestList[contestId - 1].id,
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
vm.editProblemList = data.data;
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
vm.editingContestId = 0;
|
||||
vm.editingProblemContestIndex = contestId;
|
||||
vm.editMode = vm.contestList[contestId - 1].mode;
|
||||
},
|
||||
addProblem: function () {
|
||||
vm.$fire("up!showContestProblemPage", 0, vm.contestList[vm.editingProblemContestIndex - 1].id, vm.editMode);
|
||||
},
|
||||
showProblemEditPage: function (el) {
|
||||
vm.$fire("up!showContestProblemPage", el.id, vm.contestList[vm.editingProblemContestIndex - 1].id, vm.editMode);
|
||||
},
|
||||
showSubmissionPage: function (el) {
|
||||
var problemId = 0
|
||||
if (el)
|
||||
problemId = el.id;
|
||||
vm.$fire("up!showContestSubmissionPage", problemId, vm.contestList[vm.editingProblemContestIndex - 1].id, vm.editMode);
|
||||
},
|
||||
addToProblemList: function (problem) {
|
||||
var ajaxData = {
|
||||
title: problem.title,
|
||||
description: problem.description,
|
||||
time_limit: problem.time_limit,
|
||||
memory_limit: problem.memory_limit,
|
||||
samples: [],
|
||||
test_case_id: problem.test_case_id,
|
||||
hint: problem.hint,
|
||||
source: problem.contest.title,
|
||||
visible: false,
|
||||
tags: [],
|
||||
input_description: problem.input_description,
|
||||
output_description: problem.output_description,
|
||||
difficulty: 0
|
||||
};
|
||||
for (var i = 0; i < problem.samples.length; i++) {
|
||||
ajaxData.samples.push({input: problem.samples[i].input, output: problem.samples[i].output})
|
||||
}
|
||||
$.ajax({
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/problem/",
|
||||
dataType: "json",
|
||||
data: JSON.stringify(ajaxData),
|
||||
method: "post",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
bsAlert("题目添加成功!题目现在处于隐藏状态,请到题目列表手动修改,并添加分类和难度信息!");
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
vm.$watch("showVisibleOnly", function () {
|
||||
getPageData(1);
|
||||
})
|
||||
}
|
||||
getPageData(1);
|
||||
|
||||
//init time picker
|
||||
$("#contest_start_time").datetimepicker({
|
||||
format: "yyyy-mm-dd hh:ii",
|
||||
minuteStep: 5,
|
||||
weekStart: 1,
|
||||
language: "zh-CN"
|
||||
});
|
||||
$("#contest_end_time").datetimepicker({
|
||||
format: "yyyy-mm-dd hh:ii",
|
||||
minuteStep: 5,
|
||||
weekStart: 1,
|
||||
language: "zh-CN"
|
||||
});
|
||||
|
||||
function getPageData(page) {
|
||||
var url = "/api/admin/contest/?paging=true&page=" + page + "&page_size=10";
|
||||
if (vm.showVisibleOnly)
|
||||
url += "&visible=true"
|
||||
if (vm.keyword != "")
|
||||
url += "&keyword=" + vm.keyword;
|
||||
$.ajax({
|
||||
url: url,
|
||||
dataType: "json",
|
||||
method: "get",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
vm.contestList = data.data.results;
|
||||
vm.totalPage = data.data.total_page;
|
||||
vm.previousPage = data.data.previous_page;
|
||||
vm.nextPage = data.data.next_page;
|
||||
vm.page = page;
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get group list
|
||||
$.ajax({
|
||||
url: "/api/user/",
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
var admin_type = data.data.admin_type;
|
||||
vm.admin_type = admin_type;
|
||||
if (data.data.admin_type == 1) {
|
||||
vm.isGlobal = false;
|
||||
vm.showGlobalViewRadio = false;
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
url: "/api/admin/group/",
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
if (!data.data.length) {
|
||||
|
||||
if (admin_type != 2)
|
||||
bsAlert("您的用户权限只能创建小组内比赛,但是您还没有创建过小组");
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < data.data.length; i++) {
|
||||
var item = data.data[i];
|
||||
item["isSelected"] = false;
|
||||
vm.allGroups.push(item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
avalon.scan();
|
||||
});
|
@ -14,21 +14,18 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c
|
||||
method: "post",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
//成功登陆
|
||||
var ref = document.referrer;
|
||||
if (ref) {
|
||||
// 注册页和本页的来源的跳转回首页,防止死循环
|
||||
if (ref.indexOf("register") > -1 || ref.indexOf("login") > -1) {
|
||||
location.href = "/";
|
||||
return;
|
||||
}
|
||||
// 判断来源,只有同域下才跳转
|
||||
if (ref.split("/")[2].split(":")[0] == location.hostname) {
|
||||
location.href = ref;
|
||||
return;
|
||||
}
|
||||
function getLocationVal(id){
|
||||
var temp = unescape(location.search).split(id+"=")[1] || "";
|
||||
return temp.indexOf("&")>=0 ? temp.split("&")[0] : temp;
|
||||
}
|
||||
var from = getLocationVal("__from");
|
||||
if(from != ""){
|
||||
console.log(from);
|
||||
window.location.href = from;
|
||||
}
|
||||
else{
|
||||
location.href = "/";
|
||||
}
|
||||
location.href = "/";
|
||||
}
|
||||
else {
|
||||
refresh_captcha();
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
// ------ admin web 组件 ----------
|
||||
pager: "components/pager",
|
||||
editorComponent: "components/editorComponent",
|
||||
|
||||
// ------ 下面写的都不要直接用,而是使用上面的封装版本 ------
|
||||
//富文本编辑器simditor -> editor
|
||||
@ -153,7 +154,7 @@
|
||||
},
|
||||
{
|
||||
name: "submissionList_21_pack"
|
||||
}
|
||||
},
|
||||
],
|
||||
optimizeCss: "standard",
|
||||
})
|
@ -17,8 +17,7 @@
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<textarea id="editor" placeholder="这里输入内容" autofocus ms-duplex="description"></textarea>
|
||||
<p class="error-info" ms-visible="description==''">请填写比赛描述</p>
|
||||
<ms:editor $id="contestDescriptionEditor" config="contestDescriptionEditor"></ms:editor>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@ -39,7 +38,7 @@
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label>可见范围</label>
|
||||
<label>比赛类型</label>
|
||||
|
||||
<div>
|
||||
<span ms-if="showGlobalViewRadio">
|
||||
@ -70,30 +69,12 @@
|
||||
<input type="checkbox" value="group_id" ms-duplex-checked="el.isSelected"> {{ el.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label>排名方式</label>
|
||||
<div class="form-group">
|
||||
<label><input type="radio" name="mode" ms-duplex-string="mode" value="0">
|
||||
<small>ACM</small>
|
||||
</label>
|
||||
<label><input type="radio" name="mode" ms-duplex-string="mode" value="1">
|
||||
<small>分数</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label>公开提交记录</label>
|
||||
<div class="form-group">
|
||||
<label class="text"><input type="checkbox" ms-duplex-checked="showSubmission">
|
||||
<small>公开</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
|
||||
<div class="col-md-12">
|
||||
<label>实时排名</label>
|
||||
<div class="form-group">
|
||||
<label class="text"><input type="checkbox" ms-duplex-checked="realTimeRank">
|
||||
<small>是</small>
|
||||
<small>如果不勾选,排名会被缓存,不会更新,而且只显示自己的提交。用于 acm 封榜。</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="form-group-sm">
|
||||
<label>搜索</label>
|
||||
<input name="keyWord" class="form-control" placeholder="请输入关键词" ms-duplex="keyword">
|
||||
<input type="submit" value="搜索" class="btn btn-primary" ms-click="getPage(1)">
|
||||
<input type="submit" value="搜索" class="btn btn-primary" ms-click="search()">
|
||||
</div>
|
||||
</form>
|
||||
<br>
|
||||
@ -38,10 +38,10 @@
|
||||
<label>仅显示可见 <input ms-duplex-checked="showVisibleOnly" type="checkbox"/></label>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
页数:{{ page }}/{{ totalPage }}
|
||||
<button ms-attr-class="getBtnClass('pre')" ms-click="getPrevious">上一页</button>
|
||||
<button ms-attr-class="getBtnClass('next')" ms-click="getNext">下一页</button>
|
||||
<ms:pager $id="contestListPager" config="pager"></ms:pager>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div ms-visible="editingContestId">
|
||||
<form id="edit-contest-form">
|
||||
<div class="col-md-12">
|
||||
@ -108,7 +108,7 @@
|
||||
<input type="text" class="form-control" name="password" placeholder="留空就是公开赛" ms-duplex="editPassword">
|
||||
</div>
|
||||
<div class="form-group col-md-12" ms-visible="!isGlobal">
|
||||
<!-- radio 的value 没有用 但是没有的话,表单验证会出错-->
|
||||
|
||||
<div ms-repeat="allGroups" class="col-md-4">
|
||||
<input type="checkbox" value="group_id" ms-duplex-checked="el.isSelected"> {{ el.name }}
|
||||
</div>
|
||||
@ -186,6 +186,8 @@
|
||||
|
||||
</div>
|
||||
|
||||
-->
|
||||
|
||||
|
||||
</div>
|
||||
<script src="/static/js/app/admin/contest/contestList.js"></script>
|
||||
|
@ -1,24 +0,0 @@
|
||||
{% extends "oj_base.html" %}
|
||||
{% block title %}
|
||||
授权登录
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<div class="container main">
|
||||
<div class="text-center">
|
||||
{% if request.user.is_authenticated %}
|
||||
<p>3秒钟后将跳转到<span id="link">{{ callback }}</span></p>
|
||||
<script>setTimeout(function(){
|
||||
window.location.href = "{{ callback }}?token={{ token }}"},
|
||||
3000);
|
||||
</script>
|
||||
{% else %}
|
||||
<script>window.location.href = "/login/";</script>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block js_block %}
|
||||
|
||||
{% endblock %}
|
20
template/src/oj/account/sso.html
Normal file
20
template/src/oj/account/sso.html
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends "oj_base.html" %}
|
||||
{% block title %}
|
||||
授权登录
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<div class="container main">
|
||||
<div class="text-center">
|
||||
<p>3秒钟后将使用账号{{ request.user.username }}登录<span id="link">{{ callback }}</span></p>
|
||||
<button class="btn btn-warning" onclick="location.href='/'">取消登录</button>
|
||||
<button class="btn btn-success" onclick="location.href='/login/'">更换账号</button>
|
||||
<script>setTimeout(function(){
|
||||
window.location.href = "{{ redirect_url }}"},
|
||||
3000);
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block js_block %}
|
||||
|
||||
{% endblock %}
|
@ -1,90 +1,83 @@
|
||||
{% extends "oj_base.html" %}
|
||||
{% block title %}
|
||||
|
||||
{{ user.username }}的主页
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<div class="container main">
|
||||
<div class="col-lg-4">
|
||||
<div class="avatar">
|
||||
<img src="https://coding.net/static/fruit_avatar/Fruit-1.png" class="img-responsive"
|
||||
style="height: 200px;width: 200px;">
|
||||
<img src="{{ user.userprofile.avatar }}" class="img-responsive" id="index-avatar">
|
||||
</div>
|
||||
<div>
|
||||
<h2>virusdefender</h2>
|
||||
<h2>
|
||||
{{ user.username }}
|
||||
{% ifequal user.admin_type 2 %}
|
||||
<span class="glyphicon glyphicon-star super-admin-star" title="超级管理员"></span>
|
||||
{% endifequal %}
|
||||
{% ifequal user.admin_type 1 %}
|
||||
<span class="glyphicon glyphicon-star admin-star"></span>
|
||||
{% endifequal %}
|
||||
|
||||
</h2>
|
||||
<p id="user-mood">{{ user.userprofile.mood }}</p>
|
||||
</div>
|
||||
<div class="list-group col-lg-10">
|
||||
<div class="list-group col-lg-9">
|
||||
|
||||
{% if user.userprofile.blog %}
|
||||
<p class="list-group-item"><span class="glyphicon glyphicon-link"></span>
|
||||
<a href="https://virusdefender.net">https://virusdefender.net</a>
|
||||
<a href="{{ user.userprofile.blog }}" target="_blank">{{ blog_link }}</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if user.userprofile.hduoj_username %}
|
||||
<p class="list-group-item">
|
||||
<img src="/static/img/oj_logo/hdu_logo.png" id="oj-logo">
|
||||
<a href="http://bestcoder.hdu.edu.cn/rating.php?user={{ user.userprofile.hduoj_username }}" target="_blank">
|
||||
{{ user.userprofile.hduoj_username }}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if user.userprofile.bestcoder_username %}
|
||||
<p class="list-group-item">
|
||||
<img src="/static/img/oj_logo/bestcoder_logo.png" id="oj-logo">
|
||||
<a href="http://bestcoder.hdu.edu.cn/rating.php?user={{ user.userprofile.bestcoder_username }}" target="_blank">
|
||||
{{ user.userprofile.bestcoder_username }}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if user.userprofile.codeforces_username %}
|
||||
<p class="list-group-item">
|
||||
<img src="/static/img/oj_logo/codeforces_logo.png" id="oj-logo">
|
||||
<a href="http://codeforces.com/profile/{{ user.userprofile.codeforces_username }}" target="_blank">
|
||||
{{ user.userprofile.codeforces_username }}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<p class="list-group-item">
|
||||
<img src="/static/img/oj_logo/hdu_logo.png" style="height: 20px">
|
||||
<a href="https://virusdefender.net">https://virusdefender.net</a>
|
||||
<span class="glyphicon glyphicon-calendar"></span>
|
||||
{{ user.create_time }}
|
||||
</p>
|
||||
|
||||
<p class="list-group-item">
|
||||
<img src="/static/img/oj_logo/bestcoder_logo.png" style="height: 20px">
|
||||
<a href="https://virusdefender.net">https://virusdefender.net</a>
|
||||
</p>
|
||||
|
||||
<p class="list-group-item">
|
||||
<img src="/static/img/oj_logo/codeforces_logo.png" style="height: 20px">
|
||||
<a href="https://virusdefender.net">https://virusdefender.net</a>
|
||||
</p>
|
||||
|
||||
|
||||
<p class="list-group-item"><span class="glyphicon glyphicon-calendar"></span> 2015-9-10</p>
|
||||
<div class="rows">
|
||||
<div class="col-lg-4 text-center">
|
||||
<strong id="user-data-number">{{ user.userprofile.rank }}</strong>
|
||||
<span id="user-data-text">Rank</span>
|
||||
</div>
|
||||
<div class="col-lg-4 text-center">
|
||||
<strong id="user-data-number">{{ user.userprofile.accepted_number }}</strong>
|
||||
<span id="user-data-text">AC</span>
|
||||
</div>
|
||||
<div class="col-lg-4 text-center">
|
||||
<strong id="user-data-number">{{ user.userprofile.submissions_number }}</strong>
|
||||
<span id="user-data-text">Submissions</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<ul class="nav nav-tabs" style="margin: 10px;;">
|
||||
<li role="presentation" class="active"><a href="#">Home</a></li>
|
||||
<li role="presentation"><a href="#123">全部分享</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-heading"><h3 class="panel-title">正在做的题</h3></div>
|
||||
|
||||
<div class="list-group">
|
||||
<p class="list-group-item">
|
||||
<a href="#" style="font-size: large;">problem title</a>
|
||||
<span class="right">3 / 10</span>
|
||||
<span style="display: block;">Accepted</span>
|
||||
</p>
|
||||
|
||||
<p class="list-group-item">
|
||||
<a href="#" style="font-size: large;">problem title</a>
|
||||
<span class="right">3 / 10</span>
|
||||
<span style="display: block;">Accepted</span>
|
||||
</p>
|
||||
|
||||
<p class="list-group-item">
|
||||
<a href="#" style="font-size: large;">problem title</a>
|
||||
<span class="right">3 / 10</span>
|
||||
<span style="display: block;">Accepted</span>
|
||||
</p>
|
||||
|
||||
<p class="list-group-item">
|
||||
<a href="#" style="font-size: large;">problem title</a>
|
||||
<span class="right">3 / 10</span>
|
||||
<span style="display: block;">Accepted</span>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">分享的代码</h3></div>
|
||||
<div class="panel-body"> Panel content</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block js_block %}
|
||||
<script src="/static/js/app/oj/account/register.js"></script>
|
||||
{% endblock %}
|
@ -40,7 +40,7 @@
|
||||
<th class="text-center">用时 + 罚时</th>
|
||||
{% for item in contest_problems %}
|
||||
<th class="text-center">
|
||||
<a href="/contest/{{ contest.id }}/problem/{{ item.id }}/">{{ item.sort_index }}</a>
|
||||
<a href="/contest/{{ contest.id }}/submissions/?problem_id={{ item.id }}">{{ item.sort_index }}</a>
|
||||
</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
@ -48,7 +48,7 @@
|
||||
<tbody class="rank">
|
||||
{% for item in rank %}
|
||||
<tr>
|
||||
<th scope="row">{{ forloop.counter|add:paging_info.offset}}</th>
|
||||
<th scope="row">{% if item.total_ac_number %}{{ forloop.counter|add:paging_info.offset}}{% else %}-{% endif %}</th>
|
||||
<td>
|
||||
<a href="/contest/{{ contest.id }}/submissions/?user_id={{ item.user__id }}">
|
||||
{{ item.user__username }}
|
||||
|
@ -107,14 +107,14 @@
|
||||
<ul class="pager">
|
||||
{% if previous_page %}
|
||||
<li class="previous">
|
||||
<a href="/contest/{{ contest.id }}/submissions/{{ previous_page }}/{% if filter %}?{{ filter.name }}={{ filter.content }}{% if user_id %}&user_id={{ user_id }}{% endif %}{% else %}{% if user_id %}?user_id={{ user_id }}{% endif %}{% endif %}">
|
||||
<a href="/contest/{{ contest.id }}/submissions/{{ previous_page }}/?{% if filter %}{{ filter.name }}={{ filter.content }}&{% endif %}{% if user_id %}user_id={{ user_id }}&{% endif %}{% if problem_id %}problem_id={{ problem_id }}&{% endif %}">
|
||||
<span aria-hidden="true">←</span> 上一页
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if next_page %}
|
||||
<li class="next">
|
||||
<a href="/contest/{{ contest.id }}/submissions/{{ next_page }}/{% if filter %}?{{ filter.name }}={{ filter.content }}{% if user_id %}&user_id={{ user_id }}{% endif %}{% else %}{% if user_id %}?user_id={{ user_id }}{% endif %}{% endif %}">
|
||||
<a href="/contest/{{ contest.id }}/submissions/{{ next_page }}/?{% if filter %}{{ filter.name }}={{ filter.content }}&{% endif %}{% if user_id %}user_id={{ user_id }}&{% endif %}{% if problem_id %}problem_id={{ problem_id }}&{% endif %}">
|
||||
下一页 <span aria-hidden="true">→</span>
|
||||
</a>
|
||||
</li>
|
||||
|
Loading…
Reference in New Issue
Block a user