Accept Merge Request #78 : (virusdefender-dev -> dev)
Merge Request: 修改判题模块 Created By: @hohoTT Accepted By: @hohoTT URL: https://coding.net/u/virusdefender/p/qduoj/git/merge/78
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
import pymongo
|
import pymongo
|
||||||
|
|
||||||
from bson.objectid import ObjectId
|
from bson.objectid import ObjectId
|
||||||
@@ -8,7 +9,11 @@ from client import JudgeClient
|
|||||||
from language import languages
|
from language import languages
|
||||||
from compiler import compile_
|
from compiler import compile_
|
||||||
from result import result
|
from result import result
|
||||||
from settings import judger_workspace, mongodb_config
|
from settings import judger_workspace
|
||||||
|
|
||||||
|
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
|
||||||
|
|
||||||
|
from judger_controller.settings import celery_mongodb_config, docker_mongodb_config
|
||||||
|
|
||||||
|
|
||||||
# 简单的解析命令行参数
|
# 简单的解析命令行参数
|
||||||
@@ -20,7 +25,7 @@ time_limit = args[4]
|
|||||||
memory_limit = args[6]
|
memory_limit = args[6]
|
||||||
test_case_id = args[8]
|
test_case_id = args[8]
|
||||||
|
|
||||||
connection = pymongo.MongoClient(host=mongodb_config["host"], port=mongodb_config["port"])
|
connection = pymongo.MongoClient(host=docker_mongodb_config["host"], port=docker_mongodb_config["port"])
|
||||||
collection = connection["oj"]["oj_submission"]
|
collection = connection["oj"]["oj_submission"]
|
||||||
|
|
||||||
submission = collection.find_one({"_id": ObjectId(submission_id)})
|
submission = collection.find_one({"_id": ObjectId(submission_id)})
|
||||||
@@ -40,7 +45,7 @@ try:
|
|||||||
exe_path = compile_(language, src_path, judger_workspace + "run/")
|
exe_path = compile_(language, src_path, judger_workspace + "run/")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print e
|
print e
|
||||||
connection = pymongo.MongoClient(host=mongodb_config["host"], port=mongodb_config["port"])
|
connection = pymongo.MongoClient(host=docker_mongodb_config["host"], port=docker_mongodb_config["port"])
|
||||||
collection = connection["oj"]["oj_submission"]
|
collection = connection["oj"]["oj_submission"]
|
||||||
data = {"result": result["compile_error"], "info": str(e)}
|
data = {"result": result["compile_error"], "info": str(e)}
|
||||||
collection.find_one_and_update({"_id": ObjectId(submission_id)}, {"$set": data})
|
collection.find_one_and_update({"_id": ObjectId(submission_id)}, {"$set": data})
|
||||||
@@ -72,10 +77,7 @@ except Exception as e:
|
|||||||
|
|
||||||
print "Run successfully"
|
print "Run successfully"
|
||||||
print judge_result
|
print judge_result
|
||||||
connection = pymongo.MongoClient(host=mongodb_config["host"], port=mongodb_config["port"])
|
connection = pymongo.MongoClient(host=docker_mongodb_config["host"], port=docker_mongodb_config["port"])
|
||||||
collection = connection["oj"]["oj_submission"]
|
collection = connection["oj"]["oj_submission"]
|
||||||
collection.find_one_and_update({"_id": ObjectId(submission_id)}, {"$set": judge_result})
|
collection.find_one_and_update({"_id": ObjectId(submission_id)}, {"$set": judge_result})
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -14,9 +14,4 @@ lrun_gid = 1002
|
|||||||
# judger工作目录
|
# judger工作目录
|
||||||
judger_workspace = "/var/judger/"
|
judger_workspace = "/var/judger/"
|
||||||
|
|
||||||
mongodb_config = {
|
|
||||||
"host": "192.168.59.3",
|
|
||||||
"username": "root",
|
|
||||||
"password": "root",
|
|
||||||
"port": 27017
|
|
||||||
}
|
|
||||||
@@ -7,4 +7,4 @@ app = Celery("judge", broker="redis://" +
|
|||||||
redis_config["host"] + ":" +
|
redis_config["host"] + ":" +
|
||||||
str(redis_config["port"]) +
|
str(redis_config["port"]) +
|
||||||
"/" + str(redis_config["db"]),
|
"/" + str(redis_config["db"]),
|
||||||
include=["judger_controller.tasks"])
|
include=["judge.judger_controller.tasks"])
|
||||||
32
judge/judger_controller/settings.py
Normal file
32
judge/judger_controller/settings.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
redis_config = {
|
||||||
|
"host": "121.42.196.141",
|
||||||
|
"port": 6379,
|
||||||
|
"db": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
docker_config = {
|
||||||
|
"image_name": "d622347336b8",
|
||||||
|
"docker_path": "docker",
|
||||||
|
"shell": True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
test_case_dir = "/root/test_case/"
|
||||||
|
source_code_dir = "/root/"
|
||||||
|
|
||||||
|
|
||||||
|
celery_mongodb_config = {
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"username": "root",
|
||||||
|
"password": "root",
|
||||||
|
"port": 27017
|
||||||
|
}
|
||||||
|
|
||||||
|
docker_mongodb_config = {
|
||||||
|
"host": "192.168.42.1",
|
||||||
|
"username": "root",
|
||||||
|
"password": "root",
|
||||||
|
"port": 27017
|
||||||
|
}
|
||||||
31
judge/judger_controller/tasks.py
Normal file
31
judge/judger_controller/tasks.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
# from __future__ import absolute_import
|
||||||
|
import pymongo
|
||||||
|
from bson import ObjectId
|
||||||
|
import subprocess32 as subprocess
|
||||||
|
from ..judger.result import result
|
||||||
|
from ..judger_controller.celery import app
|
||||||
|
from settings import docker_config, source_code_dir, test_case_dir, celery_mongodb_config
|
||||||
|
|
||||||
|
|
||||||
|
@app.task
|
||||||
|
def judge(submission_id, time_limit, memory_limit, test_case_id):
|
||||||
|
try:
|
||||||
|
command = "%s run -t -i --privileged --rm=true " \
|
||||||
|
"-v %s:/var/judger/test_case/ " \
|
||||||
|
"-v %s:/var/judger/code/ " \
|
||||||
|
"%s " \
|
||||||
|
"python judge/judger/run.py " \
|
||||||
|
"--solution_id %s --time_limit %s --memory_limit %s --test_case_id %s" % \
|
||||||
|
(docker_config["docker_path"],
|
||||||
|
test_case_dir,
|
||||||
|
source_code_dir,
|
||||||
|
docker_config["image_name"],
|
||||||
|
submission_id, str(time_limit), str(memory_limit), test_case_id)
|
||||||
|
subprocess.call(command, timeout=(time_limit / 1000.0 * 10), shell=docker_config["shell"])
|
||||||
|
except Exception as e:
|
||||||
|
connection = pymongo.MongoClient(host=celery_mongodb_config["host"], port=celery_mongodb_config["port"])
|
||||||
|
collection = connection["oj"]["oj_submission"]
|
||||||
|
data = {"result": result["system_error"], "info": str(e)}
|
||||||
|
collection.find_one_and_update({"_id": ObjectId(submission_id)}, {"$set": data})
|
||||||
|
connection.close()
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
# coding=utf-8
|
|
||||||
redis_config = {
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": 6379,
|
|
||||||
"db": 0
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# coding=utf-8
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from judger_controller.celery import app
|
|
||||||
import subprocess32 as subprocess
|
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
|
||||||
def judge(solution_id, time_limit, memory_limit, test_case_id):
|
|
||||||
try:
|
|
||||||
subprocess.call("docker run -t -i --privileged --rm=true "
|
|
||||||
"-v /Users/virusdefender/Desktop/test_case/:/var/judger/test_case/ "
|
|
||||||
"-v /Users/virusdefender/Desktop/:/var/judger/code/ "
|
|
||||||
"judger "
|
|
||||||
"python judger/run.py "
|
|
||||||
"--solution_id %s --time_limit %s --memory_limit %s --test_case_id %s" %
|
|
||||||
(solution_id, str(time_limit), str(memory_limit), test_case_id),
|
|
||||||
# 设置最长运行时间是5倍的 cpu 时间
|
|
||||||
timeout=(time_limit / 1000.0 * 5), shell=True)
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
print "docker timeout"
|
|
||||||
@@ -16,8 +16,9 @@ DATABASES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 这是web 服务器连接到mongodb 的地址
|
||||||
MONGODB = {
|
MONGODB = {
|
||||||
'HOST': '127.0.0.1',
|
'HOST': '121.42.196.141',
|
||||||
'USERNAME': 'root',
|
'USERNAME': 'root',
|
||||||
'PASSWORD': 'root',
|
'PASSWORD': 'root',
|
||||||
'PORT': 27017
|
'PORT': 27017
|
||||||
@@ -26,4 +27,4 @@ MONGODB = {
|
|||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
# 同理 这是 web 服务器的上传路径
|
# 同理 这是 web 服务器的上传路径
|
||||||
TEST_CASE_DIR = "/Users/virusdefender/Desktop/test_case/"
|
TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case')
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ urlpatterns = [
|
|||||||
url(r'^api/announcements/$', AnnouncementAPIView.as_view(), name="announcement_list_api"),
|
url(r'^api/announcements/$', AnnouncementAPIView.as_view(), name="announcement_list_api"),
|
||||||
url(r'^admin/contest/$', TemplateView.as_view(template_name="admin/contest/add_contest.html"),
|
url(r'^admin/contest/$', TemplateView.as_view(template_name="admin/contest/add_contest.html"),
|
||||||
name="add_contest_page"),
|
name="add_contest_page"),
|
||||||
url(r'^problems/$', TemplateView.as_view(template_name="oj/problem/problem_list.html"),
|
url(r'^problems/$', "problem.views.problem_list_page", name="problem_list_page"),
|
||||||
name="problem_list_page"),
|
url(r'^problems/(?P<page>\d+)/$', "problem.views.problem_list_page", name="problem_list_page"),
|
||||||
url(r'^admin/template/(?P<template_dir>\w+)/(?P<template_name>\w+).html$', AdminTemplateView.as_view(),
|
url(r'^admin/template/(?P<template_dir>\w+)/(?P<template_name>\w+).html$', AdminTemplateView.as_view(),
|
||||||
name="admin_template"),
|
name="admin_template"),
|
||||||
url(r'^api/admin/group/$', GroupAdminAPIView.as_view(), name="group_admin_api"),
|
url(r'^api/admin/group/$', GroupAdminAPIView.as_view(), name="group_admin_api"),
|
||||||
|
|||||||
@@ -33,8 +33,14 @@ class CreateProblemSerializer(serializers.Serializer):
|
|||||||
hint = serializers.CharField(max_length=3000, required=False, default=None)
|
hint = serializers.CharField(max_length=3000, required=False, default=None)
|
||||||
|
|
||||||
|
|
||||||
|
class ProblemTagSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ProblemTag
|
||||||
|
|
||||||
|
|
||||||
class ProblemSerializer(serializers.ModelSerializer):
|
class ProblemSerializer(serializers.ModelSerializer):
|
||||||
samples = JSONField()
|
samples = JSONField()
|
||||||
|
tags = ProblemTagSerializer(many=True)
|
||||||
|
|
||||||
class UserSerializer(serializers.ModelSerializer):
|
class UserSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -58,17 +64,11 @@ class EditProblemSerializer(serializers.Serializer):
|
|||||||
time_limit = serializers.IntegerField()
|
time_limit = serializers.IntegerField()
|
||||||
memory_limit = serializers.IntegerField()
|
memory_limit = serializers.IntegerField()
|
||||||
difficulty = serializers.IntegerField()
|
difficulty = serializers.IntegerField()
|
||||||
tags = serializers.ListField(child=serializers.IntegerField())
|
tags = serializers.ListField(child=serializers.CharField(max_length=20))
|
||||||
samples = ProblemSampleSerializer()
|
samples = ProblemSampleSerializer()
|
||||||
hint = serializers.CharField(max_length=10000)
|
hint = serializers.CharField(max_length=10000)
|
||||||
visible = serializers.BooleanField()
|
visible = serializers.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ProblemTagSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ProblemTag
|
|
||||||
|
|
||||||
|
|
||||||
class CreateProblemTagSerializer(serializers.Serializer):
|
class CreateProblemTagSerializer(serializers.Serializer):
|
||||||
name = serializers.CharField(max_length=10)
|
name = serializers.CharField(max_length=10)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import json
|
|||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ class ProblemAdminAPIView(APIView):
|
|||||||
serializer = CreateProblemSerializer(data=request.data)
|
serializer = CreateProblemSerializer(data=request.data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
data = serializer.data
|
data = serializer.data
|
||||||
|
print data
|
||||||
problem = Problem.objects.create(title=data["title"],
|
problem = Problem.objects.create(title=data["title"],
|
||||||
description=data["description"],
|
description=data["description"],
|
||||||
input_description=data["input_description"],
|
input_description=data["input_description"],
|
||||||
@@ -113,20 +115,30 @@ class ProblemAdminAPIView(APIView):
|
|||||||
# 删除原有的标签的对应关系
|
# 删除原有的标签的对应关系
|
||||||
problem.tags.remove(*problem.tags.all())
|
problem.tags.remove(*problem.tags.all())
|
||||||
# 重新添加所有的标签
|
# 重新添加所有的标签
|
||||||
problem.tags.add(*ProblemTag.objects.filter(id__in=data["tags"]))
|
for tag in data["tags"]:
|
||||||
|
try:
|
||||||
|
tag = ProblemTag.objects.get(name=tag)
|
||||||
|
except ProblemTag.DoesNotExist:
|
||||||
|
tag = ProblemTag.objects.create(name=tag)
|
||||||
|
problem.tags.add(tag)
|
||||||
problem.save()
|
problem.save()
|
||||||
return success_response(ProblemSerializer(problem).data)
|
return success_response(ProblemSerializer(problem).data)
|
||||||
else:
|
else:
|
||||||
return serializer_invalid_response(serializer)
|
return serializer_invalid_response(serializer)
|
||||||
|
|
||||||
|
|
||||||
class ProblemAPIView(APIView):
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
"""
|
"""
|
||||||
题目分页json api接口
|
题目分页json api接口
|
||||||
---
|
---
|
||||||
response_serializer: ProblemSerializer
|
response_serializer: ProblemSerializer
|
||||||
"""
|
"""
|
||||||
|
problem_id = request.GET.get("problem_id", None)
|
||||||
|
if problem_id:
|
||||||
|
try:
|
||||||
|
problem = Problem.objects.get(id=problem_id)
|
||||||
|
return success_response(ProblemSerializer(problem).data)
|
||||||
|
except Problem.DoesNotExist:
|
||||||
|
return error_response(u"题目不存在")
|
||||||
problem = Problem.objects.all().order_by("-last_update_time")
|
problem = Problem.objects.all().order_by("-last_update_time")
|
||||||
visible = request.GET.get("visible", None)
|
visible = request.GET.get("visible", None)
|
||||||
if visible:
|
if visible:
|
||||||
@@ -217,3 +229,45 @@ class TestCaseUploadAPIView(APIView):
|
|||||||
"output": l[1::2]}})
|
"output": l[1::2]}})
|
||||||
else:
|
else:
|
||||||
return error_response(u"测试用例压缩文件格式错误,请保证测试用例文件在根目录下直接压缩")
|
return error_response(u"测试用例压缩文件格式错误,请保证测试用例文件在根目录下直接压缩")
|
||||||
|
|
||||||
|
|
||||||
|
def problem_list_page(request, page=1):
|
||||||
|
# 正常情况
|
||||||
|
problems = Problem.objects.all()
|
||||||
|
|
||||||
|
# 搜索的情况
|
||||||
|
keyword = request.GET.get("keyword", None)
|
||||||
|
if keyword:
|
||||||
|
problems = problems.filter(title__contains=keyword)
|
||||||
|
|
||||||
|
# 按照标签筛选
|
||||||
|
tag_text = request.GET.get("tag", None)
|
||||||
|
if tag_text:
|
||||||
|
try:
|
||||||
|
tag = ProblemTag.objects.get(name=tag_text)
|
||||||
|
except ProblemTag.DoesNotExist:
|
||||||
|
return error_page(request, u"标签不存在")
|
||||||
|
problems = tag.problem_set.all()
|
||||||
|
|
||||||
|
paginator = Paginator(problems, 20)
|
||||||
|
try:
|
||||||
|
current_page = paginator.page(int(page))
|
||||||
|
except Exception:
|
||||||
|
return error_page(request, u"不存在的页码")
|
||||||
|
|
||||||
|
previous_page = next_page = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
previous_page = current_page.previous_page_number()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
next_page = current_page.next_page_number()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return render(request, "oj/problem/problem_list.html",
|
||||||
|
{"problems": current_page, "page": int(page),
|
||||||
|
"previous_page": previous_page, "next_page": next_page,
|
||||||
|
"keyword": keyword, "tag": tag_text})
|
||||||
|
|||||||
@@ -33,3 +33,8 @@
|
|||||||
width: 50%;
|
width: 50%;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag-editor{
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-top-color: silver;
|
||||||
|
}
|
||||||
@@ -29,3 +29,7 @@ label {
|
|||||||
[ms-controller] {
|
[ms-controller] {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.right{
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
@@ -24,17 +24,23 @@ define("admin", ["jquery", "avalon"], function ($, avalon) {
|
|||||||
var vm = avalon.define({
|
var vm = avalon.define({
|
||||||
$id: "admin",
|
$id: "admin",
|
||||||
template_url: "template/" + hash + ".html",
|
template_url: "template/" + hash + ".html",
|
||||||
group_id: -1,
|
groupId: -1,
|
||||||
|
problemId: -1,
|
||||||
hide_loading: function () {
|
hide_loading: function () {
|
||||||
$("#loading-gif").hide();
|
$("#loading-gif").hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
vm.$watch("showGroupDetailPage", function(group_id){
|
vm.$watch("showGroupDetailPage", function(groupId){
|
||||||
vm.group_id = group_id;
|
vm.groupId = groupId;
|
||||||
vm.template_url = "template/group/group_detail.html";
|
vm.template_url = "template/group/group_detail.html";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
vm.$watch("showEditProblemPage", function(problemId){
|
||||||
|
vm.problemId = problemId;
|
||||||
|
vm.template_url = "template/problem/edit_problem.html";
|
||||||
|
});
|
||||||
|
|
||||||
avalon.scan();
|
avalon.scan();
|
||||||
|
|
||||||
li_active("#li-" + hash.replace("/", "-"));
|
li_active("#li-" + hash.replace("/", "-"));
|
||||||
|
|||||||
@@ -1,171 +1,166 @@
|
|||||||
require(["jquery", "avalon", "csrf", "bs_alert", "editor", "validation"], function ($, avalon, csrfHeader, bs_alert, editor) {
|
require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "formValidation"],
|
||||||
|
function ($, avalon, csrfTokenHeader, bsAlert, editor) {
|
||||||
|
|
||||||
|
|
||||||
avalon.vmodels.announcement = null;
|
|
||||||
|
|
||||||
// avalon:定义模式 announcement
|
avalon.ready(function () {
|
||||||
avalon.ready(function () {
|
avalon.vmodels.announcement = null;
|
||||||
var announcementEditor = editor("#editor"); //创建新建公告的内容编辑器
|
|
||||||
var editAnnouncementEditor = editor("#editAnnouncementEditor");
|
|
||||||
|
|
||||||
var vm = avalon.define({
|
var createAnnouncementEditor = editor("#create-announcement-editor");
|
||||||
$id: "announcement",
|
var editAnnouncementEditor = editor("#edit-announcement-editor");
|
||||||
//通用变量
|
|
||||||
announcement: [], // 公告列表数据项
|
|
||||||
previous_page: 0, // 之前的页数
|
|
||||||
next_page: 0, // 之后的页数
|
|
||||||
page: 1, // 当前页数
|
|
||||||
isEditing: 0, // 正在编辑的公告的ID, 为零说明未在编辑
|
|
||||||
page_count: 1, // 总页数
|
|
||||||
visableOnly: false, //仅显示可见公告
|
|
||||||
// 编辑
|
|
||||||
announcementVisible: 0,
|
|
||||||
getState: function (el) { //获取公告当前状态,显示
|
|
||||||
if (el.visible)
|
|
||||||
return "可见";
|
|
||||||
else
|
|
||||||
return "隐藏";
|
|
||||||
},
|
|
||||||
getNext: function () {
|
|
||||||
if (!vm.next_page)
|
|
||||||
return;
|
|
||||||
getPageData(vm.page + 1);
|
|
||||||
},
|
|
||||||
getPrevious: function () {
|
|
||||||
if (!vm.previous_page)
|
|
||||||
return;
|
|
||||||
getPageData(vm.page - 1);
|
|
||||||
},
|
|
||||||
getBtnClass: function (btn) { //上一页/下一页按钮启用禁用逻辑
|
|
||||||
if (btn) {
|
|
||||||
return vm.next_page ? "btn btn-primary" : "btn btn-primary disabled";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return vm.previous_page ? "btn btn-primary" : "btn btn-primary disabled";
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
var vm = avalon.define({
|
||||||
enEdit: function (el) { //点击编辑按钮的事件,显示/隐藏编辑区
|
$id: "announcement",
|
||||||
$("#newTitle").val(el.title);
|
//通用变量
|
||||||
editAnnouncementEditor.setValue(el.content);
|
announcementList: [], // 公告列表数据项
|
||||||
vm.announcementVisible = el.visible;
|
previousPage: 0, // 之前的页数
|
||||||
if (vm.isEditing == el.id)
|
nextPage: 0, // 之后的页数
|
||||||
vm.isEditing = 0;
|
page: 1, // 当前页数
|
||||||
else
|
editingAnnouncementId: 0, // 正在编辑的公告的ID, 为零说明未在编辑
|
||||||
vm.isEditing = el.id;
|
totalPage: 1, // 总页数
|
||||||
editAnnouncementEditor.focus();
|
showVisibleOnly: false, //仅显示可见公告
|
||||||
},
|
// 编辑
|
||||||
disEdit: function () { //收起编辑框
|
announcementVisible: 0,
|
||||||
vm.isEditing = 0;
|
getState: function (el) { //获取公告当前状态,显示
|
||||||
},
|
if (el.visible)
|
||||||
submitChange: function () { // 处理编辑公告提交事件,顺便验证字段为空
|
return "可见";
|
||||||
var title = $("#newTitle").val(), content = editAnnouncementEditor.getValue();
|
else
|
||||||
if (title != "") {
|
return "隐藏";
|
||||||
if (content != "") {
|
},
|
||||||
$.ajax({ //发送修改公告请求
|
getNext: function () {
|
||||||
beforeSend: csrfHeader,
|
if (!vm.nextPage)
|
||||||
|
return;
|
||||||
|
getPageData(vm.page + 1);
|
||||||
|
},
|
||||||
|
getPrevious: function () {
|
||||||
|
if (!vm.previousPage)
|
||||||
|
return;
|
||||||
|
getPageData(vm.page - 1);
|
||||||
|
},
|
||||||
|
getBtnClass: function (btnType) {
|
||||||
|
if (btnType == "next") {
|
||||||
|
return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
editAnnouncement: function (announcement) {
|
||||||
|
$("#newTitle").val(announcement.title);
|
||||||
|
editAnnouncementEditor.setValue(announcement.content);
|
||||||
|
vm.announcementVisible = announcement.visible;
|
||||||
|
if (vm.editingAnnouncementId == announcement.id)
|
||||||
|
vm.editingAnnouncementId = 0;
|
||||||
|
else
|
||||||
|
vm.editingAnnouncementId = announcement.id;
|
||||||
|
editAnnouncementEditor.focus();
|
||||||
|
},
|
||||||
|
cancelEdit: function () {
|
||||||
|
vm.editingAnnouncementId = 0;
|
||||||
|
},
|
||||||
|
submitChange: function () {
|
||||||
|
var title = $("#newTitle").val();
|
||||||
|
var content = editAnnouncementEditor.getValue();
|
||||||
|
|
||||||
|
if (content && title) {
|
||||||
|
$.ajax({
|
||||||
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/admin/announcement/",
|
url: "/api/admin/announcement/",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "put",
|
method: "put",
|
||||||
data: {
|
data: {
|
||||||
id: vm.isEditing,
|
id: vm.editingAnnouncementId,
|
||||||
title: title,
|
title: title,
|
||||||
content: content,
|
content: content,
|
||||||
visible: vm.announcementVisible
|
visible: vm.announcementVisible
|
||||||
},
|
},
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
bs_alert("修改成功");
|
bsAlert("修改成功");
|
||||||
vm.isEditing = 0;
|
vm.editingAnnouncementId = 0;
|
||||||
getPageData(1);
|
getPageData(1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
bs_alert("公告内容不得为空");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
bs_alert("公告标题不能为空");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
vm.$watch("visableOnly", function () {
|
|
||||||
getPageData(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
avalon.scan();
|
|
||||||
|
|
||||||
getPageData(1); //公告列表初始化
|
|
||||||
|
|
||||||
//Ajax get数据
|
|
||||||
function getPageData(page) {
|
|
||||||
var visible = '';
|
|
||||||
if (vm.visableOnly == true)
|
|
||||||
visible = "&visible=true";
|
|
||||||
$.ajax({
|
|
||||||
beforeSend: csrfHeader,
|
|
||||||
url: "/api/announcements/?paging=true&page=" + page + "&page_size=10" + visible,
|
|
||||||
dataType: "json",
|
|
||||||
method: "get",
|
|
||||||
success: function (data) {
|
|
||||||
if (!data.code) {
|
|
||||||
vm.announcement = data.data.results;
|
|
||||||
vm.page_count = data.data.total_page;
|
|
||||||
vm.previous_page = data.data.previous_page;
|
|
||||||
vm.next_page = data.data.next_page;
|
|
||||||
vm.page = page;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert("标题和公告内容不得为空");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
vm.$watch("showVisibleOnly", function () {
|
||||||
|
getPageData(1);
|
||||||
|
});
|
||||||
|
|
||||||
//新建公告表单验证与数据提交
|
getPageData(1);
|
||||||
$("#announcement-form")
|
|
||||||
.formValidation({
|
function getPageData(page) {
|
||||||
framework: "bootstrap",
|
var url = "/api/announcements/?paging=true&page=" + page + "&page_size=10";
|
||||||
fields: {
|
if (vm.showVisibleOnly)
|
||||||
title: {
|
url += "&visible=true";
|
||||||
validators: {
|
$.ajax({
|
||||||
notEmpty: {
|
url: url,
|
||||||
message: "请填写公告标题"
|
dataType: "json",
|
||||||
|
method: "get",
|
||||||
|
success: function (data) {
|
||||||
|
if (!data.code) {
|
||||||
|
vm.announcementList = 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 {
|
||||||
|
bs_alert(data.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//新建公告表单验证与数据提交
|
||||||
|
$("#announcement-form")
|
||||||
|
.formValidation({
|
||||||
|
framework: "bootstrap",
|
||||||
|
fields: {
|
||||||
|
title: {
|
||||||
|
validators: {
|
||||||
|
notEmpty: {
|
||||||
|
message: "请填写公告标题"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
).on('success.form.fv', function (e) {
|
||||||
).on('success.form.fv', function (e) {
|
e.preventDefault();
|
||||||
e.preventDefault();
|
var title = $("#title").val();
|
||||||
var title = $("#title").val();
|
var content = createAnnouncementEditor.getValue();
|
||||||
var content = announcementEditor.getValue();
|
if (content == "") {
|
||||||
if (content == "") {
|
bsAlert("请填写公告内容");
|
||||||
bs_alert("请填写公告内容");
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
beforeSend: csrfHeader,
|
|
||||||
url: "/api/admin/announcement/",
|
|
||||||
data: {title: title, content: content},
|
|
||||||
dataType: "json",
|
|
||||||
method: "post",
|
|
||||||
success: function (data) {
|
|
||||||
if (!data.code) {
|
|
||||||
bs_alert("提交成功!");
|
|
||||||
$("#title").val("");
|
|
||||||
announcementEditor.setValue("");
|
|
||||||
getPageData(1);
|
|
||||||
} else {
|
|
||||||
bs_alert(data.data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
$.ajax({
|
||||||
});
|
beforeSend: csrfTokenHeader,
|
||||||
|
url: "/api/admin/announcement/",
|
||||||
|
data: {title: title, content: content},
|
||||||
|
dataType: "json",
|
||||||
|
method: "post",
|
||||||
|
success: function (data) {
|
||||||
|
if (!data.code) {
|
||||||
|
bsAlert("提交成功!");
|
||||||
|
$("#title").val("");
|
||||||
|
createAnnouncementEditor.setValue("");
|
||||||
|
getPageData(1);
|
||||||
|
} else {
|
||||||
|
bs_alert(data.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
avalon.scan();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,73 +1,74 @@
|
|||||||
require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, avalon, csrfHeader, bs_alert) {
|
require(["jquery", "avalon", "csrfToken", "bsAlert", "formValidation"], function ($, avalon, csrfTokenHeader, bsAlert) {
|
||||||
avalon.vmodels.group = null;
|
|
||||||
|
|
||||||
// avalon:定义模式 group_list
|
|
||||||
avalon.ready(function () {
|
avalon.ready(function () {
|
||||||
|
avalon.vmodels.group = null;
|
||||||
var vm = avalon.define({
|
var vm = avalon.define({
|
||||||
$id: "group",
|
$id: "group",
|
||||||
//通用变量
|
//通用变量
|
||||||
group_list: [], // 用户列表数据项
|
groupList: [], // 用户列表数据项
|
||||||
previous_page: 0, // 之前的页数
|
previousPage: 0, // 之前的页数
|
||||||
next_page: 0, // 之后的页数
|
nextPage: 0, // 之后的页数
|
||||||
page: 1, // 当前页数
|
page: 1, // 当前页数
|
||||||
page_count: 1, // 总页数
|
totalPage: 1, // 总页数
|
||||||
keyword: "",
|
keyword: "",
|
||||||
|
|
||||||
getNext: function () {
|
getNext: function () {
|
||||||
if (!vm.next_page)
|
if (!vm.nextPage)
|
||||||
return;
|
return;
|
||||||
getPageData(vm.page + 1);
|
getPageData(vm.page + 1);
|
||||||
},
|
},
|
||||||
getPrevious: function () {
|
getPrevious: function () {
|
||||||
if (!vm.previous_page)
|
if (!vm.previousPage)
|
||||||
return;
|
return;
|
||||||
getPageData(vm.page - 1);
|
getPageData(vm.page - 1);
|
||||||
},
|
},
|
||||||
getBtnClass: function (btn) { //上一页/下一页按钮启用禁用逻辑
|
getBtnClass: function (btnType) {
|
||||||
if (btn) {
|
if (btnType == "next") {
|
||||||
return vm.next_page ? "btn btn-primary" : "btn btn-primary disabled";
|
return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return vm.previous_page ? "btn btn-primary" : "btn btn-primary disabled";
|
return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
getPage: function (page_index) {
|
search: function(){
|
||||||
getPageData(page_index);
|
getPageData(1);
|
||||||
},
|
},
|
||||||
getGroupSettingString: function(setting){
|
getGroupSettingString: function (setting) {
|
||||||
return {0: "允许任何人加入", 1: "提交请求后管理员审核", 2: "不允许任何人加入"}[setting]
|
return {0: "允许任何人加入", 1: "提交请求后管理员审核", 2: "不允许任何人加入"}[setting]
|
||||||
},
|
},
|
||||||
showGroupDetailPage: function(group_id){
|
showGroupDetailPage: function (groupId) {
|
||||||
vm.$fire("up!showGroupDetailPage", group_id);
|
vm.$fire("up!showGroupDetailPage", groupId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
getPageData(1);
|
||||||
|
|
||||||
avalon.scan();
|
|
||||||
getPageData(1); //用户列表初始化
|
|
||||||
//Ajax get数据
|
|
||||||
function getPageData(page) {
|
function getPageData(page) {
|
||||||
var url = "/api/admin/group/?paging=true&page=" + page + "&page_size=10";
|
var url = "/api/admin/group/?paging=true&page=" + page + "&page_size=10";
|
||||||
if (vm.keyword != "")
|
if (vm.keyword)
|
||||||
url += "&keyword=" + vm.keyword;
|
url += "&keyword=" + vm.keyword;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
|
||||||
url: url,
|
url: url,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "get",
|
method: "get",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
vm.group_list = data.data.results;
|
vm.groupList = data.data.results;
|
||||||
vm.page_count = data.data.total_page;
|
vm.totalPage = data.data.total_page;
|
||||||
vm.previous_page = data.data.previous_page;
|
vm.previousPage = data.data.previous_page;
|
||||||
vm.next_page = data.data.next_page;
|
vm.nextPage = data.data.next_page;
|
||||||
vm.page = page;
|
vm.page = page;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
avalon.scan();
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -1,51 +1,50 @@
|
|||||||
require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, avalon, csrfHeader, bs_alert) {
|
require(["jquery", "avalon", "csrfToken", "bsAlert", "formValidation"], function ($, avalon, csrfTokenHeader, bsAlert) {
|
||||||
avalon.vmodels.group_detail = null;
|
|
||||||
|
|
||||||
// avalon:定义模式 group_list
|
// avalon:定义模式 group_list
|
||||||
avalon.ready(function () {
|
avalon.ready(function () {
|
||||||
|
avalon.vmodels.groupDetail = null;
|
||||||
var vm = avalon.define({
|
var vm = avalon.define({
|
||||||
$id: "group_detail",
|
$id: "groupDetail",
|
||||||
//通用变量
|
//通用变量
|
||||||
member_list: [],
|
memberList: [],
|
||||||
previous_page: 0,
|
previousPage: 0,
|
||||||
next_page: 0,
|
nextPage: 0,
|
||||||
page: 1,
|
page: 1,
|
||||||
page_count: 1,
|
totalPage: 1,
|
||||||
name: "",
|
name: "",
|
||||||
description: "",
|
description: "",
|
||||||
checked_setting: "0",
|
checkedSetting: "0",
|
||||||
|
|
||||||
getNext: function () {
|
getNext: function () {
|
||||||
if (!vm.next_page)
|
if (!vm.nextPage)
|
||||||
return;
|
return;
|
||||||
getPageData(vm.page + 1);
|
getPageData(vm.page + 1);
|
||||||
},
|
},
|
||||||
getPrevious: function () {
|
getPrevious: function () {
|
||||||
if (!vm.previous_page)
|
if (!vm.previousPage)
|
||||||
return;
|
return;
|
||||||
getPageData(vm.page - 1);
|
getPageData(vm.page - 1);
|
||||||
},
|
},
|
||||||
getBtnClass: function (btn) {
|
getBtnClass: function (btn) {
|
||||||
if (btn) {
|
if (btn == "next") {
|
||||||
return vm.next_page ? "btn btn-primary" : "btn btn-primary disabled";
|
return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return vm.previous_page ? "btn btn-primary" : "btn btn-primary disabled";
|
return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getPage: function (page_index) {
|
|
||||||
getPageData(page_index);
|
|
||||||
},
|
|
||||||
removeMember: function (relation) {
|
removeMember: function (relation) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/admin/group_member/",
|
url: "/api/admin/group_member/",
|
||||||
method: "put",
|
method: "put",
|
||||||
data: JSON.stringify({group_id: relation.group, members: [relation.user.id]}),
|
data: JSON.stringify({group_id: relation.group, members: [relation.user.id]}),
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
vm.member_list.remove(relation);
|
vm.memberList.remove(relation);
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -55,90 +54,90 @@ require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, ava
|
|||||||
getPageData(1);
|
getPageData(1);
|
||||||
function getPageData(page) {
|
function getPageData(page) {
|
||||||
var url = "/api/admin/group_member/?paging=true&page=" + page +
|
var url = "/api/admin/group_member/?paging=true&page=" + page +
|
||||||
"&page_size=10&group_id=" + avalon.vmodels.admin.group_id;
|
"&page_size=10&group_id=" + avalon.vmodels.admin.groupId;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: url,
|
url: url,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "get",
|
method: "get",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
vm.member_list = data.data.results;
|
vm.memberList = data.data.results;
|
||||||
vm.page_count = data.data.total_page;
|
vm.totalPage = data.data.total_page;
|
||||||
vm.previous_page = data.data.previous_page;
|
vm.previousPage = data.data.previous_page;
|
||||||
vm.next_page = data.data.next_page;
|
vm.nextPage = data.data.next_page;
|
||||||
vm.page = page;
|
vm.page = page;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/api/admin/group/?group_id=" + avalon.vmodels.admin.group_id,
|
url: "/api/admin/group/?group_id=" + avalon.vmodels.admin.groupId,
|
||||||
method: "get",
|
method: "get",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
vm.name = data.data.name;
|
vm.name = data.data.name;
|
||||||
vm.description = data.data.description;
|
vm.description = data.data.description;
|
||||||
vm.checked_setting = data.data.join_group_setting.toString();
|
vm.checkedSetting = data.data.join_group_setting.toString();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
$("#edit_group_form")
|
$("#edit_group_form")
|
||||||
.formValidation({
|
.formValidation({
|
||||||
framework: "bootstrap",
|
framework: "bootstrap",
|
||||||
fields: {
|
fields: {
|
||||||
name: {
|
name: {
|
||||||
validators: {
|
validators: {
|
||||||
notEmpty: {
|
notEmpty: {
|
||||||
message: "请填写小组名"
|
message: "请填写小组名"
|
||||||
},
|
},
|
||||||
stringLength: {
|
stringLength: {
|
||||||
max: 20,
|
max: 20,
|
||||||
message: '小组名长度必须在20位之内'
|
message: '小组名长度必须在20位之内'
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
description: {
|
},
|
||||||
validators: {
|
description: {
|
||||||
notEmpty: {
|
validators: {
|
||||||
message: "请填写描述"
|
notEmpty: {
|
||||||
},
|
message: "请填写描述"
|
||||||
stringLength: {
|
},
|
||||||
max: 300,
|
stringLength: {
|
||||||
message: '描述长度必须在300位之内'
|
max: 300,
|
||||||
}
|
message: '描述长度必须在300位之内'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).on('success.form.fv', function (e) {
|
}
|
||||||
|
).on('success.form.fv', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var data = {
|
var data = {
|
||||||
group_id: avalon.vmodels.admin.group_id,
|
group_id: avalon.vmodels.admin.groupId,
|
||||||
name: vm.name,
|
name: vm.name,
|
||||||
description: vm.description,
|
description: vm.description,
|
||||||
join_group_setting: vm.checked_setting
|
join_group_setting: vm.checkedSetting
|
||||||
};
|
};
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/admin/group/",
|
url: "/api/admin/group/",
|
||||||
method: "put",
|
method: "put",
|
||||||
data: data,
|
data: data,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
bs_alert("修改成功");
|
bsAlert("修改成功");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1,46 +1,47 @@
|
|||||||
require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, avalon, csrfHeader, bs_alert) {
|
require(["jquery", "avalon", "csrfToken", "bsAlert", "formValidation"], function ($, avalon, csrfTokenHeader, bsAlert) {
|
||||||
avalon.vmodels.request_list = null;
|
|
||||||
|
|
||||||
// avalon:定义模式 group_list
|
// avalon:定义模式 group_list
|
||||||
avalon.ready(function () {
|
avalon.ready(function () {
|
||||||
|
avalon.vmodels.requestList = null;
|
||||||
var vm = avalon.define({
|
var vm = avalon.define({
|
||||||
$id: "request_list",
|
$id: "requestList",
|
||||||
//通用变量
|
//通用变量
|
||||||
request_list: [], // 列表数据项
|
requestList: [], // 列表数据项
|
||||||
previous_page: 0, // 之前的页数
|
previousPage: 0, // 之前的页数
|
||||||
next_page: 0, // 之后的页数
|
nextPage: 0, // 之后的页数
|
||||||
page: 1, // 当前页数
|
page: 1, // 当前页数
|
||||||
page_count: 1, // 总页数
|
totalPage: 1, // 总页数
|
||||||
|
|
||||||
getNext: function () {
|
getNext: function () {
|
||||||
if (!vm.next_page)
|
if (!vm.nextPage)
|
||||||
return;
|
return;
|
||||||
getPageData(vm.page + 1);
|
getPageData(vm.page + 1);
|
||||||
},
|
},
|
||||||
getPrevious: function () {
|
getPrevious: function () {
|
||||||
if (!vm.previous_page)
|
if (!vm.previousPage)
|
||||||
return;
|
return;
|
||||||
getPageData(vm.page - 1);
|
getPageData(vm.page - 1);
|
||||||
},
|
},
|
||||||
getBtnClass: function (btn) { //上一页/下一页按钮启用禁用逻辑
|
getBtnClass: function (btn) { //上一页/下一页按钮启用禁用逻辑
|
||||||
if (btn) {
|
if (btn == "next") {
|
||||||
return vm.next_page ? "btn btn-primary" : "btn btn-primary disabled";
|
return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return vm.previous_page ? "btn btn-primary" : "btn btn-primary disabled";
|
return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getPage: function (page_index) {
|
getPage: function (page_index) {
|
||||||
getPageData(page_index);
|
getPageData(page_index);
|
||||||
},
|
},
|
||||||
processRequest: function(request_id, status){
|
processRequest: function(request, status){
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/admin/join_group_request/",
|
url: "/api/admin/join_group_request/",
|
||||||
method: "put",
|
method: "put",
|
||||||
data: {request_id: request_id, status: status},
|
data: {request_id: request.id, status: status},
|
||||||
success: function(data){
|
success: function(data){
|
||||||
bs_alert(data.data);
|
vm.requestList.remove(request);
|
||||||
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -52,20 +53,20 @@ require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, ava
|
|||||||
function getPageData(page) {
|
function getPageData(page) {
|
||||||
var url = "/api/admin/join_group_request/?paging=true&page=" + page + "&page_size=10";
|
var url = "/api/admin/join_group_request/?paging=true&page=" + page + "&page_size=10";
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: url,
|
url: url,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "get",
|
method: "get",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
vm.request_list = data.data.results;
|
vm.requestList = data.data.results;
|
||||||
vm.page_count = data.data.total_page;
|
vm.totalPage = data.data.total_page;
|
||||||
vm.previous_page = data.data.previous_page;
|
vm.previousPage = data.data.previous_page;
|
||||||
vm.next_page = data.data.next_page;
|
vm.nextPage = data.data.next_page;
|
||||||
vm.page = page;
|
vm.page = page;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -134,11 +135,11 @@ require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, ava
|
|||||||
method: "put",
|
method: "put",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
bs_alert("提交成功!");
|
bsAlert("提交成功!");
|
||||||
getPageData(1);
|
getPageData(1);
|
||||||
$("#password").val("");
|
$("#password").val("");
|
||||||
} else {
|
} else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1,219 +1,218 @@
|
|||||||
require(["jquery", "avalon", "editor", "uploader", "bs_alert", "csrf", "tagEditor", "validation", "jqueryUI"],
|
require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagEditor", "formValidation", "jqueryUI"],
|
||||||
function ($, avalon, editor, uploader, bs_alert, csrfHeader) {
|
function ($, avalon, editor, uploader, bsAlert, csrfTokenHeader) {
|
||||||
avalon.vmodels.add_problem = null;
|
avalon.ready(function () {
|
||||||
$("#add-problem-form")
|
avalon.vmodels.addProblem = null;
|
||||||
.formValidation({
|
$("#add-problem-form")
|
||||||
framework: "bootstrap",
|
.formValidation({
|
||||||
fields: {
|
framework: "bootstrap",
|
||||||
title: {
|
fields: {
|
||||||
validators: {
|
title: {
|
||||||
notEmpty: {
|
validators: {
|
||||||
message: "请填写题目名称"
|
notEmpty: {
|
||||||
},
|
message: "请填写题目名称"
|
||||||
stringLength: {
|
},
|
||||||
min: 1,
|
stringLength: {
|
||||||
max: 30,
|
min: 1,
|
||||||
message: "名称不能超过30个字"
|
max: 30,
|
||||||
|
message: "名称不能超过30个字"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
cpu: {
|
||||||
cpu: {
|
validators: {
|
||||||
validators: {
|
notEmpty: {
|
||||||
notEmpty: {
|
message: "请输入时间限制"
|
||||||
message: "请输入时间限制"
|
},
|
||||||
},
|
integer: {
|
||||||
integer: {
|
message: "请输入一个合法的数字"
|
||||||
message: "请输入一个合法的数字"
|
},
|
||||||
},
|
between: {
|
||||||
between: {
|
inclusive: true,
|
||||||
inclusive: true,
|
min: 1,
|
||||||
min: 1,
|
max: 5000,
|
||||||
max: 5000,
|
message: "只能在1-5000之间"
|
||||||
message: "只能在1-5000之间"
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
memory: {
|
||||||
memory: {
|
validators: {
|
||||||
validators: {
|
notEmpty: {
|
||||||
notEmpty: {
|
message: "请输入内存限制"
|
||||||
message: "请输入内存限制"
|
},
|
||||||
},
|
integer: {
|
||||||
integer: {
|
message: "请输入一个合法的数字"
|
||||||
message: "请输入一个合法的数字"
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
difficulty: {
|
||||||
difficulty: {
|
validators: {
|
||||||
validators: {
|
notEmpty: {
|
||||||
notEmpty: {
|
message: "请输入难度"
|
||||||
message: "请输入难度"
|
},
|
||||||
},
|
integer: {
|
||||||
integer: {
|
message: "难度用一个整数表示"
|
||||||
message: "难度用一个整数表示"
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
input_description: {
|
||||||
input_description: {
|
validators: {
|
||||||
validators: {
|
notEmpty: {
|
||||||
notEmpty: {
|
message: "请填写输入描述"
|
||||||
message: "请填写输入描述"
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
output_description: {
|
||||||
output_description: {
|
validators: {
|
||||||
validators: {
|
notEmpty: {
|
||||||
notEmpty: {
|
message: "请填写输出描述"
|
||||||
message: "请填写输出描述"
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
.on("success.form.fv", function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (vm.test_case_id == '') {
|
|
||||||
bs_alert("你还没有上传测试数据!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (vm.description == '') {
|
|
||||||
bs_alert("题目描述不能为空!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var ajaxData = {
|
|
||||||
title: vm.title,
|
|
||||||
description: vm.description,
|
|
||||||
time_limit: vm.cpu,
|
|
||||||
memory_limit: vm.memory,
|
|
||||||
samples: [],
|
|
||||||
test_case_id: vm.test_case_id,
|
|
||||||
hint: vm.hint,
|
|
||||||
source: vm.source,
|
|
||||||
tags: $("#tags").tagEditor("getTags")[0].tags,
|
|
||||||
input_description: vm.input_description,
|
|
||||||
output_description: vm.output_description,
|
|
||||||
difficulty: vm.difficulty
|
|
||||||
};
|
|
||||||
if (vm.samples.length == 0) {
|
|
||||||
bs_alert("请至少添加一组样例!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var i = 0; i < vm.samples.length; i++){
|
|
||||||
if (vm.samples[i].input == "" || vm.samples[i].output == ""){
|
|
||||||
bs_alert("样例输入与样例输出不能为空!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tags.length == 0) {
|
|
||||||
bs_alert("请至少添加一个标签,这将有利于用户发现你的题目!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < vm.samples.$model.length; i++) {
|
|
||||||
ajaxData.samples.push({input: vm.samples.$model[i].input, output: vm.samples.$model[i].output});
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
beforeSend: csrfHeader,
|
|
||||||
url: "/api/admin/problem/",
|
|
||||||
dataType: "json",
|
|
||||||
data: JSON.stringify(ajaxData),
|
|
||||||
method: "post",
|
|
||||||
contentType: "application/json",
|
|
||||||
success: function (data) {
|
|
||||||
if (!data.code) {
|
|
||||||
bs_alert("successful!");
|
|
||||||
console.log(data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bs_alert(data.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
});
|
.on("success.form.fv", function (e) {
|
||||||
var problemDiscription = editor("#problemDescription");
|
e.preventDefault();
|
||||||
var testCaseUploader = uploader("#testCaseFile", "/api/admin/test_case_upload/", function (file, respond) {
|
if (vm.testCaseId == "") {
|
||||||
if (respond.code)
|
bsAlert("你还没有上传测试数据!");
|
||||||
bs_alert(respond.data);
|
return;
|
||||||
else {
|
|
||||||
vm.test_case_id = respond.data.test_case_id;
|
|
||||||
vm.uploadSuccess = true;
|
|
||||||
vm.testCaseList = [];
|
|
||||||
for (var i = 0; i < respond.data.file_list.input.length; i++) {
|
|
||||||
vm.testCaseList.push({
|
|
||||||
input: respond.data.file_list.input[i],
|
|
||||||
output: respond.data.file_list.output[i]
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
bs_alert("测试数据添加成功!共添加"+vm.testCaseList.length +"组测试数据");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var hinteditor = editor("#hint");
|
|
||||||
var tagList = [], completeList = [];
|
|
||||||
var vm = avalon.define({
|
|
||||||
$id: "add_problem",
|
|
||||||
title: "",
|
|
||||||
description: "",
|
|
||||||
cpu: 1000,
|
|
||||||
memory: 256,
|
|
||||||
samples: [{input: "", output: "", "visible": true}],
|
|
||||||
hint: "",
|
|
||||||
visible: true,
|
|
||||||
difficulty: 0,
|
|
||||||
tags: [],
|
|
||||||
tag: "",
|
|
||||||
input_description: "",
|
|
||||||
output_description: "",
|
|
||||||
test_case_id: "",
|
|
||||||
testCaseList: [],
|
|
||||||
uploadSuccess: false,
|
|
||||||
source: "",
|
|
||||||
add_sample: function () {
|
|
||||||
vm.samples.push({input: "", output: "", "visible": true});
|
|
||||||
},
|
|
||||||
del_sample: function (sample) {
|
|
||||||
if (confirm("你确定要删除么?")) {
|
|
||||||
vm.samples.remove(sample);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toggle_sample: function (sample) {
|
|
||||||
sample.visible = !sample.visible;
|
|
||||||
},
|
|
||||||
getBtnContent: function (item) {
|
|
||||||
if (item.visible)
|
|
||||||
return "折叠";
|
|
||||||
return "展开";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
beforeSend: csrfHeader,
|
|
||||||
url: "/api/admin/tag/",
|
|
||||||
dataType: "json",
|
|
||||||
method: "get",
|
|
||||||
success: function (data) {
|
|
||||||
if (!data.code) {
|
|
||||||
tagList = data.data;
|
|
||||||
completeList = [];
|
|
||||||
for (var i = 0; i < tagList.length; i++) {
|
|
||||||
completeList.push(tagList[i].name);
|
|
||||||
}
|
}
|
||||||
$("#tags").tagEditor({
|
if (vm.description == "") {
|
||||||
autocomplete: {
|
bsAlert("题目描述不能为空!");
|
||||||
delay: 0, // show suggestions immediately
|
return;
|
||||||
position: {collision: 'flip'}, // automatic menu position up/down
|
}
|
||||||
source: completeList
|
if (vm.samples.length == 0) {
|
||||||
|
bsAlert("请至少添加一组样例!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < vm.samples.length; i++) {
|
||||||
|
if (vm.samples[i].input == "" || vm.samples[i].output == "") {
|
||||||
|
bsAlert("样例输入与样例输出不能为空!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
if (tags.length == 0) {
|
||||||
else {
|
bsAlert("请至少添加一个标签,这将有利于用户发现你的题目!");
|
||||||
bs_alert(data.data);
|
return;
|
||||||
}
|
}
|
||||||
}
|
var ajaxData = {
|
||||||
|
title: vm.title,
|
||||||
|
description: vm.description,
|
||||||
|
time_limit: vm.timeLimit,
|
||||||
|
memory_limit: vm.memoryLimit,
|
||||||
|
samples: [],
|
||||||
|
test_case_id: vm.testCaseId,
|
||||||
|
hint: vm.hint,
|
||||||
|
source: vm.source,
|
||||||
|
tags: $("#tags").tagEditor("getTags")[0].tags,
|
||||||
|
input_description: vm.inputDescription,
|
||||||
|
output_description: vm.outputDescription,
|
||||||
|
difficulty: vm.difficulty
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < vm.samples.$model.length; i++) {
|
||||||
|
ajaxData.samples.push({input: vm.samples.$model[i].input, output: vm.samples.$model[i].output});
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
beforeSend: csrfTokenHeader,
|
||||||
|
url: "/api/admin/problem/",
|
||||||
|
dataType: "json",
|
||||||
|
data: JSON.stringify(ajaxData),
|
||||||
|
method: "post",
|
||||||
|
contentType: "application/json",
|
||||||
|
success: function (data) {
|
||||||
|
if (!data.code) {
|
||||||
|
bsAlert("题目添加成功!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bsAlert(data.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
var testCaseUploader = uploader("#testCaseFile", "/api/admin/test_case_upload/", function (file, response) {
|
||||||
|
if (response.code)
|
||||||
|
bsAlert(response.data);
|
||||||
|
else {
|
||||||
|
vm.testCaseId = response.data.test_case_id;
|
||||||
|
vm.uploadSuccess = true;
|
||||||
|
vm.testCaseList = [];
|
||||||
|
for (var i = 0; i < response.data.file_list.input.length; i++) {
|
||||||
|
vm.testCaseList.push({
|
||||||
|
input: response.data.file_list.input[i],
|
||||||
|
output: response.data.file_list.output[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
bsAlert("测试数据添加成功!共添加" + vm.testCaseList.length + "组测试数据");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var hintEditor = editor("#hint");
|
||||||
|
var problemDescription = editor("#problemDescription");
|
||||||
|
|
||||||
|
var vm = avalon.define({
|
||||||
|
$id: "addProblem",
|
||||||
|
title: "",
|
||||||
|
description: "",
|
||||||
|
cpu: 1000,
|
||||||
|
memory: 256,
|
||||||
|
samples: [{input: "", output: "", "visible": true}],
|
||||||
|
hint: "",
|
||||||
|
visible: true,
|
||||||
|
difficulty: 0,
|
||||||
|
tags: [],
|
||||||
|
inputDescription: "",
|
||||||
|
outputDescription: "",
|
||||||
|
testCaseId: "",
|
||||||
|
testCaseList: [],
|
||||||
|
uploadSuccess: false,
|
||||||
|
source: "",
|
||||||
|
addSample: function () {
|
||||||
|
vm.samples.push({input: "", output: "", "visible": true});
|
||||||
|
},
|
||||||
|
delSample: function (sample) {
|
||||||
|
if (confirm("你确定要删除么?")) {
|
||||||
|
vm.samples.remove(sample);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleSample: function (sample) {
|
||||||
|
sample.visible = !sample.visible;
|
||||||
|
},
|
||||||
|
getBtnContent: function (item) {
|
||||||
|
if (item.visible)
|
||||||
|
return "折叠";
|
||||||
|
return "展开";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var tagAutoCompleteList = [];
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
beforeSend: csrfTokenHeader,
|
||||||
|
url: "/api/admin/tag/",
|
||||||
|
dataType: "json",
|
||||||
|
method: "get",
|
||||||
|
success: function (data) {
|
||||||
|
if (!data.code) {
|
||||||
|
for (var i = 0; i < data.data.length; i++) {
|
||||||
|
tagAutoCompleteList.push(data.data[i].name);
|
||||||
|
}
|
||||||
|
$("#tags").tagEditor({
|
||||||
|
autocomplete: {
|
||||||
|
delay: 0, // show suggestions immediately
|
||||||
|
position: {collision: 'flip'}, // automatic menu position up/down
|
||||||
|
source: tagAutoCompleteList
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bsAlert(data.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
avalon.scan();
|
avalon.scan();
|
||||||
});
|
});
|
||||||
257
static/src/js/app/admin/problem/edit_problem.js
Normal file
257
static/src/js/app/admin/problem/edit_problem.js
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagEditor", "formValidation", "jqueryUI"],
|
||||||
|
function ($, avalon, editor, uploader, bsAlert, csrfTokenHeader) {
|
||||||
|
|
||||||
|
avalon.ready(function () {
|
||||||
|
avalon.vmodels.editProblem = null;
|
||||||
|
|
||||||
|
$("#edit-problem-form")
|
||||||
|
.formValidation({
|
||||||
|
framework: "bootstrap",
|
||||||
|
fields: {
|
||||||
|
title: {
|
||||||
|
validators: {
|
||||||
|
notEmpty: {
|
||||||
|
message: "请填写题目名称"
|
||||||
|
},
|
||||||
|
stringLength: {
|
||||||
|
min: 1,
|
||||||
|
max: 30,
|
||||||
|
message: "名称不能超过30个字"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cpu: {
|
||||||
|
validators: {
|
||||||
|
notEmpty: {
|
||||||
|
message: "请输入时间限制"
|
||||||
|
},
|
||||||
|
integer: {
|
||||||
|
message: "请输入一个合法的数字"
|
||||||
|
},
|
||||||
|
between: {
|
||||||
|
inclusive: true,
|
||||||
|
min: 1,
|
||||||
|
max: 5000,
|
||||||
|
message: "只能在1-5000之间"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
memory: {
|
||||||
|
validators: {
|
||||||
|
notEmpty: {
|
||||||
|
message: "请输入内存限制"
|
||||||
|
},
|
||||||
|
integer: {
|
||||||
|
message: "请输入一个合法的数字"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
difficulty: {
|
||||||
|
validators: {
|
||||||
|
notEmpty: {
|
||||||
|
message: "请输入难度"
|
||||||
|
},
|
||||||
|
integer: {
|
||||||
|
message: "难度用一个整数表示"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
input_description: {
|
||||||
|
validators: {
|
||||||
|
notEmpty: {
|
||||||
|
message: "请填写输入描述"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
output_description: {
|
||||||
|
validators: {
|
||||||
|
notEmpty: {
|
||||||
|
message: "请填写输出描述"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on("success.form.fv", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (vm.testCaseId == "") {
|
||||||
|
bsAlert("你还没有上传测试数据!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (vm.description == "") {
|
||||||
|
bsAlert("题目描述不能为空!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (vm.samples.length == 0) {
|
||||||
|
bsAlert("请至少添加一组样例!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < vm.samples.length; i++) {
|
||||||
|
if (vm.samples[i].input == "" || vm.samples[i].output == "") {
|
||||||
|
bsAlert("样例输入与样例输出不能为空!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tags.length == 0) {
|
||||||
|
bsAlert("请至少添加一个标签,这将有利于用户发现你的题目!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var ajaxData = {
|
||||||
|
id: avalon.vmodels.admin.problemId,
|
||||||
|
title: vm.title,
|
||||||
|
description: vm.description,
|
||||||
|
time_limit: vm.timeLimit,
|
||||||
|
memory_limit: vm.memoryLimit,
|
||||||
|
samples: [],
|
||||||
|
test_case_id: vm.testCaseId,
|
||||||
|
hint: vm.hint,
|
||||||
|
source: vm.source,
|
||||||
|
visible: vm.visible,
|
||||||
|
tags: $("#tags").tagEditor("getTags")[0].tags,
|
||||||
|
input_description: vm.inputDescription,
|
||||||
|
output_description: vm.outputDescription,
|
||||||
|
difficulty: vm.difficulty
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < vm.samples.$model.length; i++) {
|
||||||
|
ajaxData.samples.push({input: vm.samples.$model[i].input, output: vm.samples.$model[i].output});
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
beforeSend: csrfTokenHeader,
|
||||||
|
url: "/api/admin/problem/",
|
||||||
|
dataType: "json",
|
||||||
|
data: JSON.stringify(ajaxData),
|
||||||
|
method: "put",
|
||||||
|
contentType: "application/json",
|
||||||
|
success: function (data) {
|
||||||
|
if (!data.code) {
|
||||||
|
bsAlert("题目编辑成功!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bsAlert(data.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
var vm = avalon.define({
|
||||||
|
$id: "editProblem",
|
||||||
|
title: "",
|
||||||
|
description: "",
|
||||||
|
timeLimit: -1,
|
||||||
|
memoryLimit: -1,
|
||||||
|
samples: [],
|
||||||
|
hint: "",
|
||||||
|
visible: true,
|
||||||
|
difficulty: 0,
|
||||||
|
inputDescription: "",
|
||||||
|
outputDescription: "",
|
||||||
|
testCaseIdd: "",
|
||||||
|
uploadSuccess: false,
|
||||||
|
source: "",
|
||||||
|
testCaseList: [],
|
||||||
|
addSample: function () {
|
||||||
|
vm.samples.push({input: "", output: "", "visible": true});
|
||||||
|
},
|
||||||
|
delSample: function (sample) {
|
||||||
|
if (confirm("你确定要删除么?")) {
|
||||||
|
vm.samples.remove(sample);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleSample: function (sample) {
|
||||||
|
sample.visible = !sample.visible;
|
||||||
|
},
|
||||||
|
getBtnContent: function (item) {
|
||||||
|
if (item.visible)
|
||||||
|
return "折叠";
|
||||||
|
return "展开";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var hintEditor = editor("#hint");
|
||||||
|
var descriptionEditor = editor("#problemDescription");
|
||||||
|
var testCaseUploader = uploader("#testCaseFile", "/api/admin/test_case_upload/", function (file, response) {
|
||||||
|
if (response.code)
|
||||||
|
bsAlert(response.data);
|
||||||
|
else {
|
||||||
|
vm.testCaseId = response.data.test_case_id;
|
||||||
|
vm.uploadSuccess = true;
|
||||||
|
vm.testCaseList = [];
|
||||||
|
for (var i = 0; i < response.data.file_list.input.length; i++) {
|
||||||
|
vm.testCaseList.push({
|
||||||
|
input: response.data.file_list.input[i],
|
||||||
|
output: response.data.file_list.output[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
bsAlert("测试数据添加成功!共添加" + vm.testCaseList.length + "组测试数据");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/admin/problem/?problem_id=" + avalon.vmodels.admin.problemId,
|
||||||
|
method: "get",
|
||||||
|
dataType: "json",
|
||||||
|
success: function (data) {
|
||||||
|
if (data.code) {
|
||||||
|
bsAlert(data.data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var problem = data.data;
|
||||||
|
console.log(problem);
|
||||||
|
vm.title = problem.title;
|
||||||
|
vm.description = problem.description;
|
||||||
|
vm.timeLimit = problem.time_limit;
|
||||||
|
vm.memoryLimit = problem.memory_limit;
|
||||||
|
for (var i = 0; i < problem.samples.length; i++) {
|
||||||
|
vm.samples.push({
|
||||||
|
input: problem.samples[i].input,
|
||||||
|
output: problem.samples[i].output,
|
||||||
|
visible: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
vm.hint = problem.hint;
|
||||||
|
vm.visible = problem.visible;
|
||||||
|
vm.difficulty = problem.difficulty;
|
||||||
|
vm.inputDescription = problem.input_description;
|
||||||
|
vm.outputDescription = problem.output_description;
|
||||||
|
vm.testCaseId = problem.test_case_id;
|
||||||
|
vm.source = problem.source;
|
||||||
|
var problemTags = problem.tags;
|
||||||
|
hintEditor.setValue(vm.hint);
|
||||||
|
descriptionEditor.setValue(vm.description);
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/admin/tag/",
|
||||||
|
dataType: "json",
|
||||||
|
method: "get",
|
||||||
|
success: function (data) {
|
||||||
|
if (!data.code) {
|
||||||
|
var tagAutoCompleteList = [], tags = [];
|
||||||
|
for (var i = 0; i < data.data.length; i++) {
|
||||||
|
tagAutoCompleteList.push(data.data[i].name);
|
||||||
|
}
|
||||||
|
for (var j = 0; j < problem.tags.length; j++) {
|
||||||
|
tags.push(problemTags[j].name);
|
||||||
|
}
|
||||||
|
$("#tags").tagEditor({
|
||||||
|
initialTags: tags,
|
||||||
|
autocomplete: {
|
||||||
|
delay: 0,
|
||||||
|
position: {collision: 'flip'},
|
||||||
|
source: tagAutoCompleteList
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bsAlert(data.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
avalon.scan();
|
||||||
|
|
||||||
|
});
|
||||||
65
static/src/js/app/admin/problem/problem.js
Normal file
65
static/src/js/app/admin/problem/problem.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
require(["jquery", "avalon", "csrfToken", "bsAlert", "formValidation"], function ($, avalon, csrfTokenHeader, bsAlert) {
|
||||||
|
|
||||||
|
avalon.ready(function () {
|
||||||
|
avalon.vmodels.problemList = null;
|
||||||
|
var vm = avalon.define({
|
||||||
|
$id: "problemList",
|
||||||
|
problemList: [],
|
||||||
|
previousPage: 0,
|
||||||
|
nextPage: 0,
|
||||||
|
page: 1,
|
||||||
|
totalPage: 1,
|
||||||
|
keyword: "",
|
||||||
|
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);
|
||||||
|
},
|
||||||
|
showEditProblemPage: function (problem_id) {
|
||||||
|
vm.$fire("up!showEditProblemPage", problem_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function getPageData(page) {
|
||||||
|
var url = "/api/admin/problem/?paging=true&page=" + page + "&page_size=10";
|
||||||
|
if (vm.keyword != "")
|
||||||
|
url += "&keyword=" + vm.keyword;
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
dataType: "json",
|
||||||
|
method: "get",
|
||||||
|
success: function (data) {
|
||||||
|
if (!data.code) {
|
||||||
|
vm.problemList = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getPageData(1);
|
||||||
|
});
|
||||||
|
avalon.scan();
|
||||||
|
});
|
||||||
@@ -1,59 +1,58 @@
|
|||||||
require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, avalon, csrfHeader, bs_alert) {
|
require(["jquery", "avalon", "csrfToken", "bsAlert", "formValidation"], function ($, avalon, csrfTokenHeader, bsAlert) {
|
||||||
avalon.vmodels.user_list = null;
|
|
||||||
|
|
||||||
// avalon:定义模式 user_list
|
|
||||||
|
// avalon:定义模式 userList
|
||||||
avalon.ready(function () {
|
avalon.ready(function () {
|
||||||
|
avalon.vmodels.userList = null;
|
||||||
var vm = avalon.define({
|
var vm = avalon.define({
|
||||||
$id: "user_list",
|
$id: "userList",
|
||||||
//通用变量
|
//通用变量
|
||||||
user_list: [], // 用户列表数据项
|
userList: [],
|
||||||
previous_page: 0, // 之前的页数
|
previousPage: 0,
|
||||||
next_page: 0, // 之后的页数
|
nextPage: 0,
|
||||||
page: 1, // 当前页数
|
page: 1,
|
||||||
isEditing: 0, // 正在编辑的公告的ID, 为零说明未在编辑
|
editingUserId: 0,
|
||||||
page_count: 1, // 总页数
|
totalPage: 1,
|
||||||
user_type: ["一般用户", "管理员", "超级管理员"],
|
userType: ["一般用户", "管理员", "超级管理员"],
|
||||||
key_word: "",
|
keyword: "",
|
||||||
showAdminOnly: false,
|
showAdminOnly: false,
|
||||||
//编辑区域同步变量
|
//编辑区域同步变量
|
||||||
username: "",
|
username: "",
|
||||||
real_name: "",
|
realName: "",
|
||||||
email: "",
|
email: "",
|
||||||
admin_type: 0,
|
adminType: 0,
|
||||||
id: 0,
|
id: 0,
|
||||||
last_login: "",
|
|
||||||
create_time: "",
|
|
||||||
getNext: function () {
|
getNext: function () {
|
||||||
if (!vm.next_page)
|
if (!vm.nextPage)
|
||||||
return;
|
return;
|
||||||
getPageData(vm.page + 1);
|
getPageData(vm.page + 1);
|
||||||
},
|
},
|
||||||
getPrevious: function () {
|
getPrevious: function () {
|
||||||
if (!vm.previous_page)
|
if (!vm.previousPage)
|
||||||
return;
|
return;
|
||||||
getPageData(vm.page - 1);
|
getPageData(vm.page - 1);
|
||||||
},
|
},
|
||||||
getBtnClass: function (btn) { //上一页/下一页按钮启用禁用逻辑
|
getBtnClass: function (btn) { //上一页/下一页按钮启用禁用逻辑
|
||||||
if (btn) {
|
if (btn) {
|
||||||
return vm.next_page ? "btn btn-primary" : "btn btn-primary disabled";
|
return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return vm.previous_page ? "btn btn-primary" : "btn btn-primary disabled";
|
return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
enEdit: function (el) { //点击编辑按钮的事件,显示/隐藏编辑区
|
editUser: function (user) { //点击编辑按钮的事件,显示/隐藏编辑区
|
||||||
vm.username = el.username;
|
vm.username = user.username;
|
||||||
vm.real_name = el.real_name;
|
vm.realName = user.real_name;
|
||||||
vm.admin_type = el.admin_type;
|
vm.adminType = user.admin_type;
|
||||||
vm.email = el.email;
|
vm.email = user.email;
|
||||||
vm.id = el.id;
|
vm.id = user.id;
|
||||||
if (vm.isEditing == el.id)
|
if (vm.editingUserId == user.id)
|
||||||
vm.isEditing = 0;
|
vm.editingUserId = 0;
|
||||||
else
|
else
|
||||||
vm.isEditing = el.id;
|
vm.editingUserId = user.id;
|
||||||
},
|
},
|
||||||
getPage: function (page_index) {
|
search: function () {
|
||||||
getPageData(page_index);
|
getPageData(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
vm.$watch("showAdminOnly", function () {
|
vm.$watch("showAdminOnly", function () {
|
||||||
@@ -66,23 +65,23 @@ require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, ava
|
|||||||
var url = "/api/admin/user/?paging=true&page=" + page + "&page_size=10";
|
var url = "/api/admin/user/?paging=true&page=" + page + "&page_size=10";
|
||||||
if (vm.showAdminOnly == true)
|
if (vm.showAdminOnly == true)
|
||||||
url += "&admin_type=1";
|
url += "&admin_type=1";
|
||||||
if (vm.key_word != "")
|
if (vm.keyword != "")
|
||||||
url += "&keyword=" + vm.key_word;
|
url += "&keyword=" + vm.keyword;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: url,
|
url: url,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "get",
|
method: "get",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
vm.user_list = data.data.results;
|
vm.userList = data.data.results;
|
||||||
vm.page_count = data.data.total_page;
|
vm.totalPage = data.data.total_page;
|
||||||
vm.previous_page = data.data.previous_page;
|
vm.previousPage = data.data.previous_page;
|
||||||
vm.next_page = data.data.next_page;
|
vm.nextPage = data.data.next_page;
|
||||||
vm.page = page;
|
vm.page = page;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -136,26 +135,26 @@ require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, ava
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var data = {
|
var data = {
|
||||||
username: vm.username,
|
username: vm.username,
|
||||||
real_name: vm.real_name,
|
real_name: vm.realName,
|
||||||
email: vm.email,
|
email: vm.email,
|
||||||
id: vm.id,
|
id: vm.id,
|
||||||
admin_type: vm.admin_type
|
admin_type: vm.adminType
|
||||||
};
|
};
|
||||||
if ($("#password").val() !== "")
|
if ($("#password").val() !== "")
|
||||||
data.password = $("#password").val();
|
data.password = $("#password").val();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/admin/user/",
|
url: "/api/admin/user/",
|
||||||
data: data,
|
data: data,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "put",
|
method: "put",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
bs_alert("提交成功!");
|
bsAlert("提交成功!");
|
||||||
getPageData(1);
|
getPageData(1);
|
||||||
$("#password").val("");
|
$("#password").val("");
|
||||||
} else {
|
} else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
require(["jquery", "bs_alert", "csrf", "validation"], function ($, bs_alert, csrfHeader) {
|
require(["jquery", "bsAlert", "csrfToken", "formValidation"], function ($, bsAlert, csrfTokenHeader) {
|
||||||
$("#change_password-form").formValidation({
|
$("#change_password-form").formValidation({
|
||||||
framework: "bootstrap",
|
framework: "bootstrap",
|
||||||
fields: {
|
fields: {
|
||||||
@@ -47,21 +47,20 @@ require(["jquery", "bs_alert", "csrf", "validation"], function ($, bs_alert, csr
|
|||||||
).on('success.form.fv', function (e) {
|
).on('success.form.fv', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var username = $("#username").val();
|
var username = $("#username").val();
|
||||||
var new_password = $("#new_password ").val();
|
var newPassword = $("#new_password ").val();
|
||||||
var password = $("#password").val();
|
var password = $("#password").val();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/change_password/",
|
url: "/api/change_password/",
|
||||||
data: {username: username, new_password: new_password, old_password: password},
|
data: {username: username, new_password: newPassword, old_password: password},
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "post",
|
method: "post",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
|
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
window.location.href = "/login/";
|
window.location.href = "/login/";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
require(["jquery", "bs_alert", "csrf", "validation"], function ($, bs_alert, csrfHeader) {
|
require(["jquery", "bsAlert", "csrfToken", "formValidation"], function ($, bsAlert, csrfTokenHeader) {
|
||||||
$("#login-form")
|
$("#login-form")
|
||||||
.formValidation({
|
.formValidation({
|
||||||
framework: "bootstrap",
|
framework: "bootstrap",
|
||||||
@@ -24,7 +24,7 @@ require(["jquery", "bs_alert", "csrf", "validation"], function ($, bs_alert, csr
|
|||||||
var username = $("#username").val();
|
var username = $("#username").val();
|
||||||
var password = $("#password").val();
|
var password = $("#password").val();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/login/",
|
url: "/api/login/",
|
||||||
data: {username: username, password: password},
|
data: {username: username, password: password},
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
@@ -34,7 +34,7 @@ require(["jquery", "bs_alert", "csrf", "validation"], function ($, bs_alert, csr
|
|||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
require(["jquery", "bs_alert", "csrf", "validation"], function ($, bs_alert, csrfHeader) {
|
require(["jquery", "bsAlert", "csrfToken", "validation"], function ($, bsAlert, csrfTokenHeader) {
|
||||||
$("#register-form")
|
$("#register-form")
|
||||||
.formValidation({
|
.formValidation({
|
||||||
framework: "bootstrap",
|
framework: "bootstrap",
|
||||||
@@ -73,13 +73,13 @@ require(["jquery", "bs_alert", "csrf", "validation"], function ($, bs_alert, csr
|
|||||||
).on('success.form.fv', function (e) {
|
).on('success.form.fv', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var username = $("#username").val();
|
var username = $("#username").val();
|
||||||
var real_name = $("#real_name").val();
|
var realName = $("#real_name").val();
|
||||||
var password = $("#password").val();
|
var password = $("#password").val();
|
||||||
var email = $("#email").val();
|
var email = $("#email").val();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfHeader,
|
||||||
url: "/api/register/",
|
url: "/api/register/",
|
||||||
data: {username: username, real_name: real_name, password: password, email: email},
|
data: {username: username, real_name: realName, password: password, email: email},
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "post",
|
method: "post",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
@@ -87,7 +87,7 @@ require(["jquery", "bs_alert", "csrf", "validation"], function ($, bs_alert, csr
|
|||||||
window.location.href = "/login/";
|
window.location.href = "/login/";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
require(["jquery", "code_mirror", "csrf", "bs_alert"], function ($, code_mirror, csrfHeader, bs_alert) {
|
require(["jquery", "codeMirror", "csrfToken", "bsAlert"], function ($, codeMirror, csrfTokenHeader, bsAlert) {
|
||||||
var code_editor = code_mirror($("#code-editor")[0], "text/x-csrc");
|
var codeEditor = codeMirror($("#code-editor")[0], "text/x-csrc");
|
||||||
var language = $("input[name='language'][checked]").val();
|
var language = $("input[name='language'][checked]").val();
|
||||||
var submission_id;
|
var submissionId;
|
||||||
|
|
||||||
$("input[name='language']").change(function () {
|
$("input[name='language']").change(function () {
|
||||||
language = this.value;
|
language = this.value;
|
||||||
var language_types = {"1": "text/x-csrc", "2": "text/x-c++src", "3": "text/x-java"};
|
var languageTypes = {"1": "text/x-csrc", "2": "text/x-c++src", "3": "text/x-java"};
|
||||||
code_editor.setOption("mode", language_types[language]);
|
codeEditor.setOption("mode", languageTypes[language]);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#show-more-btn").click(function () {
|
$("#show-more-btn").click(function () {
|
||||||
@@ -14,18 +14,17 @@ require(["jquery", "code_mirror", "csrf", "bs_alert"], function ($, code_mirror,
|
|||||||
$("#show-more-btn").hide();
|
$("#show-more-btn").hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
function show_loading() {
|
function showLoading() {
|
||||||
$("#submit-code-button").attr("disabled", "disabled");
|
$("#submit-code-button").attr("disabled", "disabled");
|
||||||
$("#loading-gif").show();
|
$("#loading-gif").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide_loading() {
|
function hideLoading() {
|
||||||
$("#submit-code-button").removeAttr("disabled");
|
$("#submit-code-button").removeAttr("disabled");
|
||||||
$("#loading-gif").hide();
|
$("#loading-gif").hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getResultHtml(data) {
|
||||||
function get_result_html(data) {
|
|
||||||
// 0 结果正确 1 运行错误 2 超时 3 超内存 4 编译错误
|
// 0 结果正确 1 运行错误 2 超时 3 超内存 4 编译错误
|
||||||
// 5 格式错误 6 结果错误 7 系统错误 8 等待判题
|
// 5 格式错误 6 结果错误 7 系统错误 8 等待判题
|
||||||
var results = {
|
var results = {
|
||||||
@@ -49,14 +48,14 @@ require(["jquery", "code_mirror", "csrf", "bs_alert"], function ($, code_mirror,
|
|||||||
if (!data.result) {
|
if (!data.result) {
|
||||||
html += "CPU time: " + data.accepted_answer_info.time + "ms ";
|
html += "CPU time: " + data.accepted_answer_info.time + "ms ";
|
||||||
}
|
}
|
||||||
html += ('<a href="/my_submission/' + submission_id + '/" target="_blank">查看详情</a></div> </div>');
|
html += ('<a href="/my_submission/' + submissionId + '/" target="_blank">查看详情</a></div> </div>');
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_result() {
|
function getResult() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/api/submission/?submission_id=" + submission_id,
|
url: "/api/submission/?submission_id=" + submissionId,
|
||||||
method: "get",
|
method: "get",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
@@ -64,54 +63,54 @@ require(["jquery", "code_mirror", "csrf", "bs_alert"], function ($, code_mirror,
|
|||||||
// 8是还没有完成判题
|
// 8是还没有完成判题
|
||||||
if (data.data.result == 8) {
|
if (data.data.result == 8) {
|
||||||
// 1秒之后重新去获取
|
// 1秒之后重新去获取
|
||||||
setTimeout(get_result, 1000);
|
setTimeout(getResult, 1000);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
hide_loading();
|
hideLoading();
|
||||||
$("#result").html(get_result_html(data.data));
|
$("#result").html(getResultHtml(data.data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bsAlert(data.data);
|
||||||
hide_loading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#submit-code-button").click(function () {
|
$("#submit-code-button").click(function () {
|
||||||
var problem_id = window.location.pathname.split("/")[2];
|
var problemId = window.location.pathname.split("/")[2];
|
||||||
var code = code_editor.getValue();
|
var code = codeEditor.getValue();
|
||||||
|
|
||||||
show_loading();
|
showLoading();
|
||||||
|
|
||||||
if(!code.trim()){
|
if(!code.trim()){
|
||||||
bs_alert("请填写代码!");
|
bs_alert("请填写代码!");
|
||||||
hide_loading();
|
hideLoading();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#result").html("");
|
$("#result").html("");
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/submission/",
|
url: "/api/submission/",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
problem_id: window.location.pathname.split("/")[2],
|
problem_id: problemId,
|
||||||
language: language,
|
language: language,
|
||||||
code: code_editor.getValue()
|
code: codeEditor.getValue()
|
||||||
}),
|
}),
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
submission_id = data.data.submission_id;
|
submissionId = data.data.submission_id;
|
||||||
// 获取到id 之后2秒去查询一下判题结果
|
// 获取到id 之后2秒去查询一下判题结果
|
||||||
setTimeout(get_result, 2000);
|
setTimeout(getResult, 2000);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bs_alert(data.data);
|
bs_alert(data.data);
|
||||||
hide_loading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,24 +2,28 @@ var require = {
|
|||||||
// RequireJS 通过一个相对的路径 baseUrl来加载所有代码。baseUrl通常被设置成data-main属性指定脚本的同级目录。
|
// RequireJS 通过一个相对的路径 baseUrl来加载所有代码。baseUrl通常被设置成data-main属性指定脚本的同级目录。
|
||||||
baseUrl: "/static/js/",
|
baseUrl: "/static/js/",
|
||||||
paths: {
|
paths: {
|
||||||
//百度webuploader
|
|
||||||
webuploader: "lib/webuploader/webuploader",
|
|
||||||
|
|
||||||
jquery: "lib/jquery/jquery",
|
jquery: "lib/jquery/jquery",
|
||||||
avalon: "lib/avalon/avalon",
|
avalon: "lib/avalon/avalon",
|
||||||
editor: "utils/editor",
|
editor: "utils/editor",
|
||||||
uploader: "utils/uploader",
|
uploader: "utils/uploader",
|
||||||
validation: "utils/validation",
|
formValidation: "utils/formValidation",
|
||||||
code_mirror: "utils/code_mirror",
|
codeMirror: "utils/codeMirror",
|
||||||
bs_alert: "utils/bs_alert",
|
bsAlert: "utils/bsAlert",
|
||||||
problem: "app/oj/problem/problem",
|
problem: "app/oj/problem/problem",
|
||||||
contest: "app/admin/contest/contest",
|
contest: "app/admin/contest/contest",
|
||||||
csrf: "utils/csrf",
|
csrfToken: "utils/csrfToken",
|
||||||
admin: "app/admin/admin",
|
admin: "app/admin/admin",
|
||||||
chart: "lib/chart/Chart",
|
chart: "lib/chart/Chart",
|
||||||
tagEditor: "lib/tagEditor/jquery.tag-editor.min",
|
tagEditor: "lib/tagEditor/jquery.tag-editor.min",
|
||||||
jqueryUI: "lib/jqueryUI/jquery-ui",
|
jqueryUI: "lib/jqueryUI/jquery-ui",
|
||||||
//formValidation 不要在代码中单独使用,而是使用和修改utils/validation
|
bootstrap: "lib/bootstrap/bootstrap",
|
||||||
|
datetimePicker: "lib/datetime_picker/bootstrap-datetimepicker.zh-CN",
|
||||||
|
|
||||||
|
|
||||||
|
// ------ 下面写的都不要直接用,而是使用上面的封装版本 ------
|
||||||
|
|
||||||
|
//formValidation -> utils/validation
|
||||||
base: "lib/formValidation/base",
|
base: "lib/formValidation/base",
|
||||||
helper: "lib/formValidation/helper",
|
helper: "lib/formValidation/helper",
|
||||||
"language/zh_CN": "lib/formValidation/language/zh_CN",
|
"language/zh_CN": "lib/formValidation/language/zh_CN",
|
||||||
@@ -32,26 +36,25 @@ var require = {
|
|||||||
"validator/confirm":"lib/formValidation/validator/confirm",
|
"validator/confirm":"lib/formValidation/validator/confirm",
|
||||||
"validator/remote":"lib/formValidation/validator/remote",
|
"validator/remote":"lib/formValidation/validator/remote",
|
||||||
"validator/emailAddress":"lib/formValidation/validator/emailAddress",
|
"validator/emailAddress":"lib/formValidation/validator/emailAddress",
|
||||||
//富文本编辑器 不要直接使用,而是使用上面的editor
|
|
||||||
|
//富文本编辑器simditor -> editor
|
||||||
simditor: "lib/simditor/simditor",
|
simditor: "lib/simditor/simditor",
|
||||||
"simple-module": "lib/simditor/module",
|
"simple-module": "lib/simditor/module",
|
||||||
"simple-hotkeys": "lib/simditor/hotkeys",
|
"simple-hotkeys": "lib/simditor/hotkeys",
|
||||||
"simple-uploader": "lib/simditor/uploader",
|
"simple-uploader": "lib/simditor/uploader",
|
||||||
|
|
||||||
//code mirroe 代码编辑器
|
//code mirror 代码编辑器 ->codeMirror
|
||||||
_code_mirror: "lib/codeMirror/codemirror",
|
_codeMirror: "lib/codeMirror/codemirror",
|
||||||
code_mirror_clang: "lib/codeMirror/language/clike",
|
codeMirrorClang: "lib/codeMirror/language/clike",
|
||||||
|
|
||||||
//bootstrap
|
//百度webuploader -> uploader
|
||||||
bootstrap: "lib/bootstrap/bootstrap",
|
webUploader: "lib/webuploader/webuploader",
|
||||||
|
|
||||||
//
|
"_datetimePicker": "lib/datetime_picker/bootstrap-datetimepicker"
|
||||||
"_datetimepicker": "lib/datetime_picker/bootstrap-datetimepicker",
|
|
||||||
"datetimepicker": "lib/datetime_picker/bootstrap-datetimepicker.zh-CN"
|
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
"bootstrap": {"deps": ['jquery']},
|
bootstrap: {deps: ["jquery"]},
|
||||||
"_datetimepicker": {"deps": ["jquery"]},
|
_datetimePicker: {dep: ["jquery"]},
|
||||||
"datetimepicker": {"deps": ["_datetimepicker"]}
|
datetimePicker: {deps: ["_datetimePicker"]}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
mod(require("../../lib/codemirror"));
|
mod(require("../../lib/codemirror"));
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
define(["_code_mirror"], mod);
|
define(["_codeMirror"], mod);
|
||||||
else // Plain browser env
|
else // Plain browser env
|
||||||
mod(CodeMirror);
|
mod(CodeMirror);
|
||||||
})(function(CodeMirror) {
|
})(function(CodeMirror) {
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
// AMD module is defined
|
// AMD module is defined
|
||||||
if (typeof define === "function" && define.amd) {
|
if (typeof define === "function" && define.amd) {
|
||||||
define("validator/remote", ["jquery", "base", "csrf"], factory);
|
define("validator/remote", ["jquery", "base", "csrfToken"], factory);
|
||||||
} else {
|
} else {
|
||||||
// planted over the root!
|
// planted over the root!
|
||||||
factory(root.jQuery, root.FormValidation);
|
factory(root.jQuery, root.FormValidation);
|
||||||
}
|
}
|
||||||
}(this, function ($, FormValidation, csrfHeader) {
|
}(this, function ($, FormValidation, csrfTokenHeader) {
|
||||||
FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
|
FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
|
||||||
'en_US': {
|
'en_US': {
|
||||||
remote: {
|
remote: {
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
return true;
|
return true;
|
||||||
var url = options.url;
|
var url = options.url;
|
||||||
var xhr = $.ajax({
|
var xhr = $.ajax({
|
||||||
beforeSend: csrfHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: url,
|
url: url,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
data: ajaxData,
|
data: ajaxData,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
define("bs_alert", ["jquery", "bootstrap"], function($){
|
define("bsAlert", ["jquery", "bootstrap"], function($){
|
||||||
function bs_alert(content){
|
function bsAlert(content){
|
||||||
if(!$("#alert-modal").length) {
|
if(!$("#alert-modal").length) {
|
||||||
var html = '<div class="modal fade" id="alert-modal" tabindex="-1" role="dialog"> ' +
|
var html = '<div class="modal fade" id="alert-modal" tabindex="-1" role="dialog"> ' +
|
||||||
'<div class="modal-dialog modal-sm"> <div class="modal-content"> <div class="modal-header"> ' +
|
'<div class="modal-dialog modal-sm"> <div class="modal-content"> <div class="modal-header"> ' +
|
||||||
@@ -13,5 +13,5 @@ define("bs_alert", ["jquery", "bootstrap"], function($){
|
|||||||
$("#modal-text").html(content);
|
$("#modal-text").html(content);
|
||||||
$("#alert-modal").modal();
|
$("#alert-modal").modal();
|
||||||
}
|
}
|
||||||
return bs_alert;
|
return bsAlert;
|
||||||
});
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
define("code_mirror", ["_code_mirror", "code_mirror_clang"], function(CodeMirror){
|
define("codeMirror", ["_codeMirror", "codeMirrorClang"], function(CodeMirror){
|
||||||
function code_mirror(selector, language){
|
function codeMirror(selector, language){
|
||||||
return CodeMirror.fromTextArea(selector,
|
return CodeMirror.fromTextArea(selector,
|
||||||
{
|
{
|
||||||
indentUnit: 4,
|
indentUnit: 4,
|
||||||
@@ -8,5 +8,5 @@ define("code_mirror", ["_code_mirror", "code_mirror_clang"], function(CodeMirror
|
|||||||
mode: language
|
mode: language
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return code_mirror;
|
return codeMirror;
|
||||||
});
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
define("csrf",function(){
|
define("csrfToken",function(){
|
||||||
function get_cookie(cookie_name) {
|
function getCookie(cookie_name) {
|
||||||
var name = cookie_name + "=";
|
var name = cookie_name + "=";
|
||||||
var ca = document.cookie.split(';');
|
var ca = document.cookie.split(';');
|
||||||
for (var i = 0; i < ca.length; i++) {
|
for (var i = 0; i < ca.length; i++) {
|
||||||
@@ -9,15 +9,15 @@ define("csrf",function(){
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
function csrfHeader(){
|
function csrfTokenHeader(){
|
||||||
// jquery的请求
|
// jquery的请求
|
||||||
if(arguments.length == 2) {
|
if(arguments.length == 2) {
|
||||||
arguments[0].setRequestHeader("X-CSRFToken", get_cookie("csrftoken"));
|
arguments[0].setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
|
||||||
}
|
}
|
||||||
// 百度webuploader 的请求
|
// 百度webuploader 的请求
|
||||||
else if(arguments.length == 3){
|
else if(arguments.length == 3){
|
||||||
arguments[2]["X-CSRFToken"] = get_cookie("csrftoken");
|
arguments[2]["X-CSRFToken"] = getCookie("csrftoken");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return csrfHeader;
|
return csrfTokenHeader;
|
||||||
});
|
});
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
define("validation",
|
define("formValidation",
|
||||||
[ 'base',
|
[ 'base',
|
||||||
'helper',
|
'helper',
|
||||||
'framework/bootstrap',
|
'framework/bootstrap',
|
||||||
4
static/src/js/utils/html5shiv.min.js
vendored
4
static/src/js/utils/html5shiv.min.js
vendored
@@ -1,4 +0,0 @@
|
|||||||
/**
|
|
||||||
* @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
|
||||||
*/
|
|
||||||
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document);
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
function _notify(notify_type, title, content){
|
|
||||||
$.notify({
|
|
||||||
title: title,
|
|
||||||
message: content
|
|
||||||
}, {
|
|
||||||
type: notify_type,
|
|
||||||
placement: {
|
|
||||||
from: "top",
|
|
||||||
align: "center"
|
|
||||||
},
|
|
||||||
offset: {
|
|
||||||
y: 50
|
|
||||||
},
|
|
||||||
delay: 3000,
|
|
||||||
timer: 1000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function show_info(title, content) {
|
|
||||||
_notify("info", title, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
function show_warning(title, content) {
|
|
||||||
_notify("warning", title, content);
|
|
||||||
}
|
|
||||||
5
static/src/js/utils/respond.min.js
vendored
5
static/src/js/utils/respond.min.js
vendored
@@ -1,5 +0,0 @@
|
|||||||
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
|
|
||||||
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
|
|
||||||
* */
|
|
||||||
|
|
||||||
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
define("uploader", ["webuploader", "csrf"], function(webuploader,csrf){
|
define("uploader", ["webUploader", "csrfToken"], function(webuploader,csrfTokenHeader){
|
||||||
function uploader(selector, server, onSuccess, beforeUpload) {
|
function uploader(selector, server, onSuccess, beforeUpload) {
|
||||||
var Webuploader= webuploader.create({
|
var Webuploader= webuploader.create({
|
||||||
auto: true,
|
auto: true,
|
||||||
@@ -11,9 +11,9 @@ define("uploader", ["webuploader", "csrf"], function(webuploader,csrf){
|
|||||||
pick: selector,
|
pick: selector,
|
||||||
// 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
|
// 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
|
||||||
resize: false,
|
resize: false,
|
||||||
uploadBeforeSend : csrf
|
uploadBeforeSend : csrfTokenHeader
|
||||||
});
|
});
|
||||||
Webuploader.on("uploadBeforeSend",csrf);
|
Webuploader.on("uploadBeforeSend",csrfTokenHeader);
|
||||||
Webuploader.on("uploadSuccess", onSuccess);
|
Webuploader.on("uploadSuccess", onSuccess);
|
||||||
Webuploader.on("beforeFileQueued", beforeUpload);
|
Webuploader.on("beforeFileQueued", beforeUpload);
|
||||||
return Webuploader;
|
return Webuploader;
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ from rest_framework.views import APIView
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from judger.result import result
|
from judge.judger.result import result
|
||||||
from judger_controller.tasks import judge
|
from judge.judger_controller.tasks import judge
|
||||||
from account.decorators import login_required
|
from account.decorators import login_required
|
||||||
from problem.models import Problem
|
from problem.models import Problem
|
||||||
from utils.shortcuts import serializer_invalid_response, error_response, success_response, error_page
|
from utils.shortcuts import serializer_invalid_response, error_response, success_response, error_page
|
||||||
from .serializers import CreateSubmissionSerializer
|
from .serializers import CreateSubmissionSerializer
|
||||||
|
|
||||||
|
|
||||||
def _create_mondodb_connection():
|
def _create_mongodb_connection():
|
||||||
mongodb_setting = settings.MONGODB
|
mongodb_setting = settings.MONGODB
|
||||||
connection = pymongo.MongoClient(host=mongodb_setting["HOST"], port=mongodb_setting["PORT"])
|
connection = pymongo.MongoClient(host=mongodb_setting["HOST"], port=mongodb_setting["PORT"])
|
||||||
return connection["oj"]["oj_submission"]
|
return connection["oj"]["oj_submission"]
|
||||||
@@ -42,9 +42,7 @@ class SubmissionAPIView(APIView):
|
|||||||
problem = Problem.objects.get(id=data["problem_id"])
|
problem = Problem.objects.get(id=data["problem_id"])
|
||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return error_response(u"题目不存在")
|
return error_response(u"题目不存在")
|
||||||
mongodb_setting = settings.DATABASES["mongodb"]
|
collection = _create_mongodb_connection()
|
||||||
connection = pymongo.MongoClient(host=mongodb_setting["HOST"], port=mongodb_setting["PORT"])
|
|
||||||
collection = connection["oj"]["oj_submission"]
|
|
||||||
submission_id = str(collection.insert_one(data).inserted_id)
|
submission_id = str(collection.insert_one(data).inserted_id)
|
||||||
judge.delay(submission_id, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
judge.delay(submission_id, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
||||||
return success_response({"submission_id": submission_id})
|
return success_response({"submission_id": submission_id})
|
||||||
@@ -56,7 +54,7 @@ class SubmissionAPIView(APIView):
|
|||||||
submission_id = request.GET.get("submission_id", None)
|
submission_id = request.GET.get("submission_id", None)
|
||||||
if not submission_id:
|
if not submission_id:
|
||||||
return error_response(u"参数错误")
|
return error_response(u"参数错误")
|
||||||
submission = _create_mondodb_connection().find_one({"_id": ObjectId(submission_id), "user_id": request.user.id})
|
submission = _create_mongodb_connection().find_one({"_id": ObjectId(submission_id), "user_id": request.user.id})
|
||||||
if submission:
|
if submission:
|
||||||
response_data = {"result": submission["result"]}
|
response_data = {"result": submission["result"]}
|
||||||
if submission["result"] == 0:
|
if submission["result"] == 0:
|
||||||
@@ -68,7 +66,7 @@ class SubmissionAPIView(APIView):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def problem_my_submissions_list_page(request, problem_id):
|
def problem_my_submissions_list_page(request, problem_id):
|
||||||
collection = _create_mondodb_connection()
|
collection = _create_mongodb_connection()
|
||||||
submissions = collection.find({"problem_id": int(problem_id), "user_id": request.user.id},
|
submissions = collection.find({"problem_id": int(problem_id), "user_id": request.user.id},
|
||||||
projection=["result", "accepted_answer_info", "create_time", "language"],
|
projection=["result", "accepted_answer_info", "create_time", "language"],
|
||||||
sort=[["create_time", -pymongo.ASCENDING]])
|
sort=[["create_time", -pymongo.ASCENDING]])
|
||||||
@@ -82,7 +80,7 @@ def problem_my_submissions_list_page(request, problem_id):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def my_submission(request, submission_id):
|
def my_submission(request, submission_id):
|
||||||
collection = _create_mondodb_connection()
|
collection = _create_mongodb_connection()
|
||||||
submission = collection.find_one({"user_id": request.user.id, "_id": ObjectId(submission_id)},
|
submission = collection.find_one({"user_id": request.user.id, "_id": ObjectId(submission_id)},
|
||||||
projection=["result", "accepted_answer_info", "create_time",
|
projection=["result", "accepted_answer_info", "create_time",
|
||||||
"language", "code", "problem_id", "info"])
|
"language", "code", "problem_id", "info"])
|
||||||
|
|||||||
@@ -101,9 +101,6 @@
|
|||||||
<li class="list-group-item" id="li-user-user_list">
|
<li class="list-group-item" id="li-user-user_list">
|
||||||
<a href="#user/user_list">用户列表</a>
|
<a href="#user/user_list">用户列表</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item" id="li-user-user_group">
|
|
||||||
<a href="#user/user_group">用户分组</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-header">小组管理</li>
|
<li class="list-group-header">小组管理</li>
|
||||||
<li class="list-group-item" id="li-group-group">
|
<li class="list-group-item" id="li-group-group">
|
||||||
<a href="#group/group">小组列表</a>
|
<a href="#group/group">小组列表</a>
|
||||||
@@ -124,8 +121,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="/static/js/config.js"></script>
|
<script src="/static/js/config.js"></script>
|
||||||
<script src="/static/js/require.js"></script>
|
<script src="/static/js/require.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<div ms-controller="announcement" class="col-md-9">
|
<div ms-controller="announcement" class="col-md-9">
|
||||||
<h1>Announcement</h1>
|
<h1>公告管理</h1>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<tr>
|
<tr>
|
||||||
<th>编号</th>
|
<th>编号</th>
|
||||||
@@ -8,36 +8,38 @@
|
|||||||
<th>更新时间</th>
|
<th>更新时间</th>
|
||||||
<th>创建者</th>
|
<th>创建者</th>
|
||||||
<th>状态</th>
|
<th>状态</th>
|
||||||
<th>操作</th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ms-repeat="announcement">
|
<tr ms-repeat="announcementList">
|
||||||
<td>{{el.id}}</td>
|
<td>{{ el.id }}</td>
|
||||||
<td>{{el.title}}</td>
|
<td>{{ el.title }}</td>
|
||||||
<td>{{el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
<td>{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||||
<td>{{el.last_update_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
<td>{{ el.last_update_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||||
<td>{{el.created_by.username}}</td>
|
<td>{{ el.created_by.username }}</td>
|
||||||
<td>{{getState(el)}}</td>
|
<td>{{ getState(el)}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn-sm btn-info" ms-click="enEdit(el)">编辑</button>
|
<button class="btn-sm btn-info" ms-click="editAnnouncement(el)">编辑</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>仅显示可见 <input ms-duplex-checked="visableOnly" type="checkbox"/></label>
|
<label>仅显示可见 <input ms-duplex-checked="showVisibleOnly" type="checkbox"/></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right">
|
<div class="right">
|
||||||
页数:{{page}}/{{page_count}}
|
页数:{{ page }}/{{ totalPage }}
|
||||||
<button ms-attr-class="getBtnClass(0)" ms-click="getPrevious">上一页</button>
|
<button ms-attr-class="getBtnClass('pre')" ms-click="getPrevious">上一页</button>
|
||||||
<button ms-attr-class="getBtnClass(1)" ms-click="getNext">下一页</button>
|
<button ms-attr-class="getBtnClass('next')" ms-click="getNext">下一页</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ms-visible="isEditing">
|
<div ms-visible="editingAnnouncementId">
|
||||||
<h3>编辑公告</h3>
|
<h3>编辑公告</h3>
|
||||||
<div class="form-group"><label for="title">标题</label>
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>标题</label>
|
||||||
<input name="title" type="text" class="form-control" id="newTitle" placeholder="公告标题" value=""></div>
|
<input name="title" type="text" class="form-control" id="newTitle" placeholder="公告标题" value=""></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>内容</label>
|
<label>内容</label>
|
||||||
<textarea id="editAnnouncementEditor"></textarea>
|
<textarea id="edit-announcement-editor"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>可见 <input ms-duplex-checked="announcementVisible" type="checkbox"/></label>
|
<label>可见 <input ms-duplex-checked="announcementVisible" type="checkbox"/></label>
|
||||||
@@ -45,17 +47,17 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button ms-click="submitChange()" class="btn btn-primary">提交</button>
|
<button ms-click="submitChange()" class="btn btn-primary">提交</button>
|
||||||
|
|
||||||
<button ms-click="disEdit()" class="btn btn-danger">取消</button>
|
<button ms-click="cancelEdit()" class="btn btn-danger">取消</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3>添加公告</h3>
|
<h3>添加公告</h3>
|
||||||
|
|
||||||
<form id="announcement-form">
|
<form id="announcement-form">
|
||||||
<div class="form-group"><label for="title">标题</label>
|
<div class="form-group"><label>标题</label>
|
||||||
<input name="title" type="text" class="form-control" id="title" placeholder="公告标题"></div>
|
<input name="title" type="text" class="form-control" id="title" placeholder="公告标题"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>内容</label>
|
<label>内容</label>
|
||||||
<textarea id="editor" placeholder="公告内容"></textarea>
|
<textarea id="create-announcement-editor" placeholder="公告内容"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button type="submit" class="btn btn-primary">提交</button>
|
<button type="submit" class="btn btn-primary">提交</button>
|
||||||
|
|||||||
@@ -75,13 +75,18 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label>添加题目</label>
|
<label>添加题目</label>
|
||||||
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="add_problem()">添加</a>
|
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="add_problem()">添加</a>
|
||||||
<div class="col-md-12">
|
|
||||||
<label>上传测试用例</label>
|
<div class="col-md-12">
|
||||||
<label>选择题号</label><select ms-duplex="problemNo"><option value="-1">未指定</option><option ms-repeat="problems" ms-attr-value="$index+1">{{$index+1}}</option></select>
|
<label>上传测试用例</label>
|
||||||
<div id="uploader">
|
<label>选择题号</label><select ms-duplex="problemNo">
|
||||||
<div>选择文件</div>
|
<option value="-1">未指定</option>
|
||||||
</div>
|
<option ms-repeat="problems" ms-attr-value="$index+1">{{$index+1}}</option>
|
||||||
</div>
|
</select>
|
||||||
|
|
||||||
|
<div id="uploader">
|
||||||
|
<div>选择文件</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="problem" ms-repeat-problem="problems">
|
<div class="problem" ms-repeat-problem="problems">
|
||||||
@@ -89,7 +94,7 @@
|
|||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<span class="panel-title">题目{{$index + 1}} </span>
|
<span class="panel-title">题目{{$index + 1}} </span>
|
||||||
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="toggle(problem)">
|
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="toggle(problem)">
|
||||||
{{getBtnContent(problem)}}
|
{{ getBtnContent(problem)}}
|
||||||
</a>
|
</a>
|
||||||
<a href="javascript:void(0)" class="btn btn-danger btn-sm" ms-click="del_problem(problem)">
|
<a href="javascript:void(0)" class="btn btn-danger btn-sm" ms-click="del_problem(problem)">
|
||||||
删除
|
删除
|
||||||
@@ -97,17 +102,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel-body" ms-visible="problem.visible">
|
<div class="panel-body" ms-visible="problem.visible">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group col-md-12">
|
||||||
<label>题目标题</label>
|
<label>题目标题</label>
|
||||||
<input type="text" name="problem_name[]" class="form-control" ms-duplex="problem.title">
|
<input type="text" name="problem_name[]" class="form-control" ms-duplex="problem.title">
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-md-12">
|
||||||
|
<label>题目描述</label>
|
||||||
|
<textarea ms-attr-id="problem-{{ problem.id }}-description" placeholder="这里输入内容"
|
||||||
|
ms-duplex="problem.description"></textarea>
|
||||||
|
<small ms-visible="problem.description==''" style="color:red">请填写题目描述</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-12">
|
|
||||||
<label>题目描述</label>
|
|
||||||
<textarea ms-attr-id="problem-{{ problem.id }}-description" placeholder="这里输入内容" ms-duplex="problem.description"></textarea>
|
|
||||||
<small ms-visible="problem.description==''" style="color:red">请填写题目描述</small>
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group col-md-12">
|
||||||
<label>提示</label>
|
<label>提示</label>
|
||||||
<textarea ms-attr-id="problem-{{ problem.id }}-hint" placeholder="这里输入内容" ms-duplex="problem.hint"></textarea>
|
<textarea ms-attr-id="problem-{{ problem.id }}-hint" placeholder="这里输入内容"
|
||||||
|
ms-duplex="problem.hint"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 form-group">
|
<div class="col-md-3 form-group">
|
||||||
<label>cpu</label>
|
<label>cpu</label>
|
||||||
@@ -119,19 +126,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 form-group">
|
<div class="col-md-3 form-group">
|
||||||
<label>难度</label>
|
<label>难度</label>
|
||||||
<input type="number" name="difficulty[]" class="form-control" ms-duplex="problem.difficulty">
|
<input type="number" name="difficulty[]" class="form-control"
|
||||||
|
ms-duplex="problem.difficulty">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label>样例</label>
|
<label>样例</label>
|
||||||
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="add_sample(problem)">添加</a>
|
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
|
||||||
|
ms-click="add_sample(problem)">添加</a>
|
||||||
|
|
||||||
<div class="sample">
|
<div class="sample">
|
||||||
<div class="panel panel-default sample-panel" ms-repeat-sample="problem.samples">
|
<div class="panel panel-default sample-panel" ms-repeat-sample="problem.samples">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<span class="panel-title">样例{{$index + 1}}</span>
|
<span class="panel-title">样例{{$index + 1}}</span>
|
||||||
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="toggle(sample)">
|
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
|
||||||
{{getBtnContent(sample)}}
|
ms-click="toggle(sample)">
|
||||||
|
{{ getBtnContent(sample)}}
|
||||||
</a>
|
</a>
|
||||||
<a href="javascript:void(0)" class="btn btn-danger btn-sm" ms-click="del_sample(problem, sample)">
|
<a href="javascript:void(0)" class="btn btn-danger btn-sm"
|
||||||
|
ms-click="del_sample(problem, sample)">
|
||||||
删除
|
删除
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -167,8 +179,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr ms-repeat="problem.testCaseList">
|
<tr ms-repeat="problem.testCaseList">
|
||||||
<td>{{$index}}</td>
|
<td>{{$index}}</td>
|
||||||
<td>{{el.input}}</td>
|
<td>{{ el.input }}</td>
|
||||||
<td>{{el.output}}</td>
|
<td>{{ el.output }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<div ms-controller="group" class="col-md-9">
|
<div ms-controller="group" class="col-md-9">
|
||||||
<h1>小组管理</h1>
|
<h1>小组管理</h1>
|
||||||
<div class="text-right">
|
|
||||||
|
<div class="right">
|
||||||
<form class="form-inline" onsubmit="return false;">
|
<form class="form-inline" onsubmit="return false;">
|
||||||
<div class="form-group-sm">
|
<div class="form-group-sm">
|
||||||
<label>搜索</label>
|
<label>搜索</label>
|
||||||
<input class="form-control" placeholder="请输入关键词" ms-duplex="keyword">
|
<input 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>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<br>
|
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -20,10 +20,10 @@
|
|||||||
<th>设置</th>
|
<th>设置</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ms-repeat="group_list">
|
<tr ms-repeat="groupList">
|
||||||
<td>{{el.id}}</td>
|
<td>{{ el.id }}</td>
|
||||||
<td>{{el.name}}</td>
|
<td>{{ el.name }}</td>
|
||||||
<td>{{el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
<td>{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||||
<td>{{ el.members_number }}</td>
|
<td>{{ el.members_number }}</td>
|
||||||
<td>{{ getGroupSettingString(el.join_group_setting) }}</td>
|
<td>{{ getGroupSettingString(el.join_group_setting) }}</td>
|
||||||
|
|
||||||
@@ -33,10 +33,10 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="right">
|
||||||
页数:{{page}}/{{page_count}}
|
页数:{{ page }}/{{ totalPage }}
|
||||||
<button ms-attr-class="getBtnClass(0)" ms-click="getPrevious">上一页</button>
|
<button ms-attr-class="getBtnClass('pre')" ms-click="getPrevious">上一页</button>
|
||||||
<button ms-attr-class="getBtnClass(1)" ms-click="getNext">下一页</button>
|
<button ms-attr-class="getBtnClass('next')" ms-click="getNext">下一页</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div ms-controller="group_detail" class="col-md-9">
|
<div ms-controller="groupDetail" class="col-md-9">
|
||||||
<h1>小组成员管理</h1>
|
<h1>小组成员管理</h1>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
<th>加入时间</th>
|
<th>加入时间</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ms-repeat="member_list">
|
<tr ms-repeat="memberList">
|
||||||
<td>{{ el.user.id }}</td>
|
<td>{{ el.user.id }}</td>
|
||||||
<td>{{ el.user.username }}</td>
|
<td>{{ el.user.username }}</td>
|
||||||
<td>{{ el.user.real_name }}</td>
|
<td>{{ el.user.real_name }}</td>
|
||||||
@@ -21,9 +21,9 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
页数:{{ page }}/{{ page_count }}
|
页数:{{ page }}/{{ totalPage }}
|
||||||
<button ms-attr-class="getBtnClass(0)" ms-click="getPrevious">上一页</button>
|
<button ms-attr-class="getBtnClass('pre')" ms-click="getPrevious">上一页</button>
|
||||||
<button ms-attr-class="getBtnClass(1)" ms-click="getNext">下一页</button>
|
<button ms-attr-class="getBtnClass('next')" ms-click="getNext">下一页</button>
|
||||||
</div>
|
</div>
|
||||||
<h1>修改小组信息</h1>
|
<h1>修改小组信息</h1>
|
||||||
|
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
||||||
<label>加入小组设置</label>
|
<label>加入小组设置</label>
|
||||||
<input type="radio" name="join_group_setting" value="0" ms-duplex-string="checked_setting">允许任何人加入
|
<input type="radio" name="join_group_setting" value="0" ms-duplex-string="checkedSetting">允许任何人加入
|
||||||
<input type="radio" name="join_group_setting" value="1" ms-duplex-string="checked_setting">提交请求后管理员审核
|
<input type="radio" name="join_group_setting" value="1" ms-duplex-string="checkedSetting">提交请求后管理员审核
|
||||||
<input type="radio" name="join_group_setting" value="2" ms-duplex-string="checked_setting">不允许任何人加入
|
<input type="radio" name="join_group_setting" value="2" ms-duplex-string="checkedSetting">不允许任何人加入
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary" type="submit">提交</button>
|
<button class="btn btn-primary" type="submit">提交</button>
|
||||||
@@ -52,4 +52,4 @@
|
|||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/js/app/admin/group/group_detail.js"></script>
|
<script src="/static/js/app/admin/group/groupDetail.js"></script>
|
||||||
@@ -1,31 +1,31 @@
|
|||||||
<div ms-controller="request_list" class="col-md-9">
|
<div ms-controller="requestList" class="col-md-9">
|
||||||
<h1>加入小组请求管理</h1>
|
<h1>加入小组请求管理</h1>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<tr>
|
<tr>
|
||||||
<th>创建时间</th>
|
<th>创建时间</th>
|
||||||
<th>用户</th>
|
|
||||||
<th>小组</th>
|
<th>小组</th>
|
||||||
|
<th>用户</th>
|
||||||
<th>附加消息</th>
|
<th>附加消息</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ms-repeat="request_list">
|
<tr ms-repeat="requestList">
|
||||||
<td>{{el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
<td>{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||||
<td>{{ el.group.name }}</td>
|
<td>{{ el.group.name }}</td>
|
||||||
<td>{{ el.user.username }}</td>
|
<td>{{ el.user.username }}</td>
|
||||||
<td>{{ el.message }}</td>
|
<td>{{ el.message }}</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<button class="btn-sm btn-success" ms-click="processRequest(el.id, true)">同意</button>
|
<button class="btn-sm btn-success" ms-click="processRequest(el, true)">同意</button>
|
||||||
<button class="btn-sm btn-danger" ms-click="processRequest(el.id, false)">拒绝</button>
|
<button class="btn-sm btn-danger" ms-click="processRequest(el, false)">拒绝</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
页数:{{page}}/{{page_count}}
|
页数:{{ page }}/{{ totalPage }}
|
||||||
<button ms-attr-class="getBtnClass(0)" ms-click="getPrevious">上一页</button>
|
<button ms-attr-class="getBtnClass('pre')" ms-click="getPrevious">上一页</button>
|
||||||
<button ms-attr-class="getBtnClass(1)" ms-click="getNext">下一页</button>
|
<button ms-attr-class="getBtnClass('next')" ms-click="getNext">下一页</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/js/app/admin/group/join_group_request_list.js"></script>
|
<script src="/static/js/app/admin/group/joinGroupRequestList.js"></script>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<div ms-controller="add_problem" class="col-md-9">
|
<div ms-controller="addProblem" class="col-md-9">
|
||||||
<form id="add-problem-form">
|
<form id="add-problem-form">
|
||||||
|
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group col-md-12">
|
||||||
@@ -41,27 +41,27 @@
|
|||||||
<div class="col-md-12 form-group">
|
<div class="col-md-12 form-group">
|
||||||
<label>输入描述</label><br>
|
<label>输入描述</label><br>
|
||||||
<textarea class="form-control" rows="5" name="input_description"
|
<textarea class="form-control" rows="5" name="input_description"
|
||||||
ms-duplex="input_description"></textarea>
|
ms-duplex="inputDescription"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12 form-group">
|
<div class="col-md-12 form-group">
|
||||||
<label>输出描述</label><br>
|
<label>输出描述</label><br>
|
||||||
<textarea class="form-control" rows="5" name="output_description"
|
<textarea class="form-control" rows="5" name="output_description"
|
||||||
ms-duplex="output_description"></textarea>
|
ms-duplex="outputDescription"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12"><br>
|
<div class="col-md-12"><br>
|
||||||
<label>样例</label>
|
<label>样例</label>
|
||||||
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="add_sample()">添加</a>
|
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="addSample()">添加</a>
|
||||||
|
|
||||||
<div class="sample">
|
<div class="sample">
|
||||||
<div class="panel panel-default sample-panel" ms-repeat-sample="samples">
|
<div class="panel panel-default sample-panel" ms-repeat-sample="samples">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<span class="panel-title">样例{{$index + 1}}</span>
|
<span class="panel-title">样例{{$index + 1}}</span>
|
||||||
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
|
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
|
||||||
ms-click="toggle_sample(sample)">
|
ms-click="toggleSample(sample)">
|
||||||
{{ getBtnContent(sample)}}
|
{{ getBtnContent(sample)}}
|
||||||
</a>
|
</a>
|
||||||
<a href="javascript:void(0)" class="btn btn-danger btn-sm"
|
<a href="javascript:void(0)" class="btn btn-danger btn-sm"
|
||||||
ms-click="del_sample(sample)">
|
ms-click="delSample(sample)">
|
||||||
删除
|
删除
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
123
template/admin/problem/edit_problem.html
Normal file
123
template/admin/problem/edit_problem.html
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<div ms-controller="editProblem" class="col-md-9">
|
||||||
|
<form id="edit-problem-form">
|
||||||
|
|
||||||
|
<div class="form-group col-md-12">
|
||||||
|
<label>题目标题</label>
|
||||||
|
<input type="text" name="title" autofocus class="form-control" ms-duplex="title">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group col-md-12">
|
||||||
|
<label>题目描述</label>
|
||||||
|
<textarea id="problemDescription" placeholder="这里输入内容(此内容不能为空)" ms-duplex="description"></textarea>
|
||||||
|
<small ms-visible="description==''" style="color:red">请填写题目描述</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="form-group"><label>时间限制(ms)</label>
|
||||||
|
<input type="number" name="cpu" class="form-control" ms-duplex="timeLimit">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="form-group"><label>内存限制(MB)</label>
|
||||||
|
<input type="number" name="memory" class="form-control" ms-duplex="memoryLimit">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="form-group"><label>难度</label>
|
||||||
|
<input type="number" name="difficulty" class="form-control" ms-duplex="difficulty">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 form-group">
|
||||||
|
<label>前台是否可见</label><br>
|
||||||
|
<label><input type="checkbox" ms-duplex-checked="visible">
|
||||||
|
<small> 可见</small>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div id="tag" class="col-md-12">
|
||||||
|
<label>标签</label><br>
|
||||||
|
<input type="text" id="tags">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12 form-group">
|
||||||
|
<label>输入描述</label><br>
|
||||||
|
<textarea class="form-control" rows="5" name="input_description"
|
||||||
|
ms-duplex="inputDescription"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12 form-group">
|
||||||
|
<label>输出描述</label><br>
|
||||||
|
<textarea class="form-control" rows="5" name="output_escription"
|
||||||
|
ms-duplex="outputDescription"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12"><br>
|
||||||
|
<label>样例</label>
|
||||||
|
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="addSample()">添加</a>
|
||||||
|
|
||||||
|
<div class="sample">
|
||||||
|
<div class="panel panel-default sample-panel" ms-repeat-sample="samples">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="panel-title">样例{{$index + 1}}</span>
|
||||||
|
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
|
||||||
|
ms-click="toggleSample(sample)">
|
||||||
|
{{ getBtnContent(sample)}}
|
||||||
|
</a>
|
||||||
|
<a href="javascript:void(0)" class="btn btn-danger btn-sm"
|
||||||
|
ms-click="delSample(sample)">
|
||||||
|
删除
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body row" ms-visible="sample.visible">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>样例输入</label>
|
||||||
|
<textarea class="form-control" rows="5" ms-duplex="sample.input"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>样例输出</label>
|
||||||
|
<textarea class="form-control" rows="5" ms-duplex="sample.output"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12"><br>
|
||||||
|
<label>测试数据(当前已上传,继续上传将覆盖原有测试用例)</label><br>
|
||||||
|
<small class="text-info">请将所有测试用例打包在一个文件中上传,所有文件要在压缩包的根目录,且输入输出文件名要以从1开始连续数字标识要对应例如:<br>
|
||||||
|
1.in 1.out 2.in 2.out
|
||||||
|
</small>
|
||||||
|
<table class="table table-striped" ms-visible="uploadSuccess">
|
||||||
|
<tr>
|
||||||
|
<td>编号</td>
|
||||||
|
<td>输入文件名</td>
|
||||||
|
<td>输出文件名</td>
|
||||||
|
</tr>
|
||||||
|
<tr ms-repeat="testCaseList">
|
||||||
|
<td>{{ $index + 1 }}</td>
|
||||||
|
<td>{{ el.input }}</td>
|
||||||
|
<td>{{ el.output }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<div id="testCaseFile">选择文件</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-md-12">
|
||||||
|
<label>提示</label>
|
||||||
|
<textarea id="hint" placeholder="这里输入内容" ms-duplex="hint"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-md-12">
|
||||||
|
<label>来源</label>
|
||||||
|
<input type="text" name="source" class="form-control" ms-duplex="source">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<input type="submit" class="btn btn-success btn-lg" value="发布题目" id="submitBtn">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/static/js/app/admin/problem/edit_problem.js"></script>
|
||||||
40
template/admin/problem/problem_list.html
Normal file
40
template/admin/problem/problem_list.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<div ms-controller="problemList" class="col-md-9">
|
||||||
|
<h1>题目列表</h1>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<form class="form-inline" onsubmit="return false;">
|
||||||
|
<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)">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>题目</th>
|
||||||
|
<th>创建时间</th>
|
||||||
|
<th>作者</th>
|
||||||
|
<td>通过次数/提交总数</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr ms-repeat="problemList">
|
||||||
|
<td>{{ el.id }}</td>
|
||||||
|
<td>{{ el.title }}</td>
|
||||||
|
<td>{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||||
|
<td>{{ el.created_by.username }}</td>
|
||||||
|
<td>{{ el.total_accepted_number }}/{{ el.total_submit_number }}</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn-sm btn-info" ms-click="showEditProblemPage(el.id)">编辑</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="/static/js/app/admin/problem/problem.js"></script>
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
<div ms-controller="user_list" class="col-md-9">
|
<div ms-controller="userList" class="col-md-9">
|
||||||
<h1>User</h1>
|
<h1>用户管理</h1>
|
||||||
<div class="text-right">
|
|
||||||
|
<div class="right">
|
||||||
<form class="form-inline" onsubmit="return false;">
|
<form class="form-inline" onsubmit="return false;">
|
||||||
<div class="form-group-sm">
|
<div class="form-group-sm">
|
||||||
<label>搜索</label>
|
<label>搜索</label>
|
||||||
<input name="keyWord" class="form-control" placeholder="请输入关键词" ms-duplex="key_word">
|
<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>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
@@ -21,16 +22,16 @@
|
|||||||
<th>用户类型</th>
|
<th>用户类型</th>
|
||||||
<th>修改</th>
|
<th>修改</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ms-repeat="user_list">
|
<tr ms-repeat="userList">
|
||||||
<td>{{el.id}}</td>
|
<td>{{ el.id }}</td>
|
||||||
<td>{{el.username}}</td>
|
<td>{{ el.username }}</td>
|
||||||
<td>{{el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
<td>{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||||
<td>{{el.last_login|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
<td>{{ el.last_login|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||||
<td>{{el.real_name}}</td>
|
<td>{{ el.real_name }}</td>
|
||||||
<td>{{el.email}}</td>
|
<td>{{ el.email }}</td>
|
||||||
<td>{{user_type[el.admin_type]}}</td>
|
<td>{{ userType[el.admin_type]}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn-sm btn-info" ms-click="enEdit(el)">编辑</button>
|
<button class="btn-sm btn-info" ms-click="editUser(el)">编辑</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -38,12 +39,13 @@
|
|||||||
<label>仅显示管理员 <input ms-duplex-checked="showAdminOnly" type="checkbox"/></label>
|
<label>仅显示管理员 <input ms-duplex-checked="showAdminOnly" type="checkbox"/></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
页数:{{page}}/{{page_count}}
|
页数:{{ page }}/{{ totalPage }}
|
||||||
<button ms-attr-class="getBtnClass(0)" ms-click="getPrevious">上一页</button>
|
<button ms-attr-class="getBtnClass('pre')" ms-click="getPrevious">上一页</button>
|
||||||
<button ms-attr-class="getBtnClass(1)" ms-click="getNext">下一页</button>
|
<button ms-attr-class="getBtnClass('next')" ms-click="getNext">下一页</button>
|
||||||
</div>
|
</div>
|
||||||
<div ms-visible="isEditing">
|
<div ms-visible="editingUserId">
|
||||||
<h3>修改用户信息</h3>
|
<h3>修改用户信息</h3>
|
||||||
|
|
||||||
<form id="edit_user-form">
|
<form id="edit_user-form">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="form-group col-md-4"><label>ID</label>
|
<div class="form-group col-md-4"><label>ID</label>
|
||||||
@@ -53,7 +55,7 @@
|
|||||||
<input name="username" type="text" class="form-control" ms-duplex="username">
|
<input name="username" type="text" class="form-control" ms-duplex="username">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-4"><label>真实姓名</label>
|
<div class="form-group col-md-4"><label>真实姓名</label>
|
||||||
<input name="real_name" type="text" class="form-control" ms-duplex="real_name">
|
<input name="real_name" type="text" class="form-control" ms-duplex="realName">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -65,8 +67,8 @@
|
|||||||
<input name="email" type="email" class="form-control" ms-duplex="email">
|
<input name="email" type="email" class="form-control" ms-duplex="email">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-4"><label>用户类型</label>
|
<div class="form-group col-md-4"><label>用户类型</label>
|
||||||
<select name="admin_type" class="form-control" ms-duplex="admin_type">
|
<select name="admin_type" class="form-control" ms-duplex="adminType">
|
||||||
<option ms-repeat="user_type" ms-attr-value="$index">{{el}}</option>
|
<option ms-repeat="userType" ms-attr-value="$index">{{ el }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,4 +78,4 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/js/app/admin/user/user_list.js"></script>
|
<script src="/static/js/app/admin/user/userList.js"></script>
|
||||||
@@ -1,34 +1,36 @@
|
|||||||
{% extends "oj_base.html" %}
|
{% extends "oj_base.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container main">
|
<div class="container main">
|
||||||
<div class="col-md-6 col-md-offset-3">
|
<div class="col-md-6 col-md-offset-3">
|
||||||
<h2 class="text-center">修改密码</h2>
|
<h2 class="text-center">修改密码</h2>
|
||||||
|
|
||||||
<form id="change_password-form">
|
<form id="change_password-form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">用户名</label>
|
<label for="username">用户名</label>
|
||||||
<input type="text" class="form-control input-lg" id="username" name="username" placeholder="用户名"
|
<input type="text" class="form-control input-lg" id="username" name="username" placeholder="用户名"
|
||||||
autofocus>
|
autofocus>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">旧密码</label>
|
<label for="password">旧密码</label>
|
||||||
<input type="password" class="form-control input-lg" id="password" name="password" placeholder="密码">
|
<input type="password" class="form-control input-lg" id="password" name="password" placeholder="密码">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new_password">新密码</label>
|
<label for="new_password">新密码</label>
|
||||||
<input type="password" class="form-control input-lg" id="new_password" name="new_password" placeholder="新密码">
|
<input type="password" class="form-control input-lg" id="new_password" name="new_password"
|
||||||
</div>
|
placeholder="新密码">
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label for="confirm_password">确认密码</label>
|
<div class="form-group">
|
||||||
<input type="password" class="form-control input-lg" id="confirm_password" name="confirm_password" placeholder="确认密码">
|
<label for="confirm_password">确认密码</label>
|
||||||
</div>
|
<input type="password" class="form-control input-lg" id="confirm_password" name="confirm_password"
|
||||||
<div class="form-group">
|
placeholder="确认密码">
|
||||||
<button type="submit" class="btn btn-primary">提交</button>
|
</div>
|
||||||
</div>
|
<div class="form-group">
|
||||||
</form>
|
<button type="submit" class="btn btn-primary">提交</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js_block %}
|
{% block js_block %}
|
||||||
<script src="/static/js/app/oj/account/change_password.js"></script>
|
<script src="/static/js/app/oj/account/change_password.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,26 +1,26 @@
|
|||||||
{% extends "oj_base.html" %}
|
{% extends "oj_base.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container main">
|
<div class="container main">
|
||||||
<div class="col-md-6 col-md-offset-3">
|
<div class="col-md-6 col-md-offset-3">
|
||||||
<h2 class="text-center">用户登录</h2>
|
<h2 class="text-center">用户登录</h2>
|
||||||
|
|
||||||
<form id="login-form">
|
<form id="login-form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">用户名</label>
|
<label for="username">用户名</label>
|
||||||
<input type="text" class="form-control input-lg" id="username" name="username" placeholder="用户名"
|
<input type="text" class="form-control input-lg" id="username" name="username" placeholder="用户名"
|
||||||
autofocus>
|
autofocus>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">密码</label>
|
<label for="password">密码</label>
|
||||||
<input type="password" class="form-control input-lg" id="password" name="password" placeholder="密码">
|
<input type="password" class="form-control input-lg" id="password" name="password" placeholder="密码">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button type="submit" class="btn btn-primary">提交</button>
|
<button type="submit" class="btn btn-primary">提交</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js_block %}
|
{% block js_block %}
|
||||||
<script src="/static/js/app/oj/account/login.js"></script>
|
<script src="/static/js/app/oj/account/login.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,38 +1,39 @@
|
|||||||
{% extends "oj_base.html" %}
|
{% extends "oj_base.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container main">
|
<div class="container main">
|
||||||
<div class="col-md-6 col-md-offset-3">
|
<div class="col-md-6 col-md-offset-3">
|
||||||
<h2 class="text-center">用户注册</h2>
|
<h2 class="text-center">用户注册</h2>
|
||||||
|
|
||||||
<form id="register-form">
|
<form id="register-form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">用户名</label>
|
<label for="username">用户名</label>
|
||||||
<input type="text" class="form-control input-lg" id="username" name="username" placeholder="用户名"
|
<input type="text" class="form-control input-lg" id="username" name="username" placeholder="用户名"
|
||||||
autofocus>
|
autofocus>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="real_name">真实姓名</label>
|
<label for="real_name">真实姓名</label>
|
||||||
<input type="text" class="form-control input-lg" id="real_name" name="real_name" placeholder="真实姓名">
|
<input type="text" class="form-control input-lg" id="real_name" name="real_name" placeholder="真实姓名">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="email">邮箱地址</label>
|
<label for="email">邮箱地址</label>
|
||||||
<input type="email" class="form-control input-lg" id="email" name="email" placeholder="邮箱地址">
|
<input type="email" class="form-control input-lg" id="email" name="email" placeholder="邮箱地址">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">密码</label>
|
<label for="password">密码</label>
|
||||||
<input type="password" class="form-control input-lg" id="password" name="password" placeholder="密码">
|
<input type="password" class="form-control input-lg" id="password" name="password" placeholder="密码">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="confirm_password">确认密码</label>
|
<label for="confirm_password">确认密码</label>
|
||||||
<input type="password" class="form-control input-lg" id="confirm_password" name="confirm_password" placeholder="确认密码">
|
<input type="password" class="form-control input-lg" id="confirm_password" name="confirm_password"
|
||||||
</div>
|
placeholder="确认密码">
|
||||||
<div class="form-group">
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">提交</button>
|
<div class="form-group">
|
||||||
</div>
|
<button type="submit" class="btn btn-primary">提交</button>
|
||||||
</form>
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js_block %}
|
{% block js_block %}
|
||||||
<script src="/static/js/app/oj/account/register.js"></script>
|
<script src="/static/js/app/oj/account/register.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
{% extends "oj_base.html" %}
|
{% extends "oj_base.html" %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container main">
|
<div class="container main">
|
||||||
<h1 class="text-center">{{ announcement.title }}</h1>
|
<h1 class="text-center">{{ announcement.title }}</h1>
|
||||||
|
|
||||||
<p class="text-muted text-center">
|
<p class="text-muted text-center">
|
||||||
作者:{{ announcement.created_by }}
|
作者:{{ announcement.created_by }}
|
||||||
|
|
||||||
创建时间:{{ announcement.create_time }}
|
创建时间:{{ announcement.create_time }}
|
||||||
{% ifequal announcement.create_time announcement.last_update_time %}
|
{% ifequal announcement.create_time announcement.last_update_time %}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
最后更新:{{ announcement.last_update_time }}
|
最后更新:{{ announcement.last_update_time }}
|
||||||
{% endifequal %}
|
{% endifequal %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p>{{ announcement.content|safe }}</p>
|
<p>{{ announcement.content|safe }}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
{% extends "oj_base.html" %}
|
{% extends "oj_base.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container main">
|
<div class="container main">
|
||||||
<ul class="nav nav-tabs nav-tabs-google">
|
<ul class="nav nav-tabs nav-tabs-google">
|
||||||
<li role="presentation" class="active">
|
<li role="presentation" class="active">
|
||||||
<a href="problem.html">题目</a></li>
|
<a href="problem.html">题目</a></li>
|
||||||
<li role="presentation"><a href="my_solutions_list.html">我的提交</a></li>
|
<li role="presentation"><a href="my_solutions_list.html">我的提交</a></li>
|
||||||
<li role="presentation"><a href="#">排名</a></li>
|
<li role="presentation"><a href="#">排名</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2 class="text-center">第一次比赛</h2>
|
<h2 class="text-center">第一次比赛</h2>
|
||||||
|
|
||||||
<p class="text-muted text-center"><b>开始时间:</b> 2015-6-8 19:00 <b>结束时间:</b> 2015-9-1 12:00</p>
|
<p class="text-muted text-center"><b>开始时间:</b> 2015-6-8 19:00 <b>结束时间:</b> 2015-9-1 12:00</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,37 +1,39 @@
|
|||||||
{% extends "oj_base.html" %}
|
{% extends "oj_base.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container">
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<h1>青岛大学在线评测平台</h1>
|
<h1>青岛大学在线评测平台</h1>
|
||||||
|
|
||||||
<p class="lead">走心的在线评测平台和算法交流社区,全新登场~</p>
|
<p class="lead">走心的在线评测平台和算法交流社区,全新登场~</p>
|
||||||
|
|
||||||
|
<p><a class="btn btn-lg btn-primary" href="/problems/" role="button">开始刷题!</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Example row of columns -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<h2>全新UI 全新设计</h2>
|
||||||
|
|
||||||
|
<p>精心设计的UI和交互让你。。。编不下去了 </p>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<h2>分布式评测</h2>
|
||||||
|
|
||||||
|
<p>技术领先的高性能分布式评测机制,根据提交数量自动伸缩判题机器实例。</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<h2>高质量原创题目</h2>
|
||||||
|
|
||||||
|
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id
|
||||||
|
ligula
|
||||||
|
porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum
|
||||||
|
nibh,
|
||||||
|
ut fermentum massa.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p><a class="btn btn-lg btn-primary" href="/problems/" role="button">开始刷题!</a></p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Example row of columns -->
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<h2>全新UI 全新设计</h2>
|
|
||||||
|
|
||||||
<p>精心设计的UI和交互让你。。。编不下去了 </p>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<h2>分布式评测</h2>
|
|
||||||
|
|
||||||
<p>技术领先的高性能分布式评测机制,根据提交数量自动伸缩判题机器实例。</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<h2>高质量原创题目</h2>
|
|
||||||
|
|
||||||
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula
|
|
||||||
porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh,
|
|
||||||
ut fermentum massa.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<h2 class="text-center">{{ problem.title }}</h2>
|
<h2 class="text-center">{{ problem.title }}</h2>
|
||||||
|
|
||||||
<p class="text-muted text-center">发布时间 : {{ problem.create_time }}
|
<p class="text-muted text-center">发布时间 : {{ problem.create_time }}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{% extends 'oj_base.html' %}
|
{% extends 'oj_base.html' %}
|
||||||
{% block css_block %}
|
{% block css_block %}
|
||||||
<style>
|
<style>
|
||||||
.CodeMirror{
|
.CodeMirror {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
{% ifequal submission.result 4 %}
|
{% ifequal submission.result 4 %}
|
||||||
<p>{{ submission.info }}</p>
|
<p>{{ submission.info }}</p>
|
||||||
{% endifequal %}
|
{% endifequal %}
|
||||||
<p>提交时间 : {{ submission.create_time }}</p>
|
<p>提交时间 : {{ submission.create_time }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="code-field">
|
<div id="code-field">
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js_block %}
|
{% block js_block %}
|
||||||
<script>
|
<script>
|
||||||
require(["jquery", "code_mirror"], function ($, code_mirror) {
|
require(["jquery", "codeMirror"], function ($, codeMirror) {
|
||||||
{% ifequal submission.language 1 %}
|
{% ifequal submission.language 1 %}
|
||||||
var language = "text/x-csrc";
|
var language = "text/x-csrc";
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -50,8 +50,8 @@
|
|||||||
var language = "text/x-java";
|
var language = "text/x-java";
|
||||||
{% endifequal %}
|
{% endifequal %}
|
||||||
{% endifequal %}
|
{% endifequal %}
|
||||||
var code_editor = code_mirror($("#code-editor")[0], language);
|
var codeEditor = codeMirror($("#code-editor")[0], language);
|
||||||
code_editor.setOption("readOnly", true);
|
codeEditor.setOption("readOnly", true);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,11 +1,17 @@
|
|||||||
{% extends "oj_base.html" %}
|
{% extends "oj_base.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
{% load problem %}
|
||||||
<div class="container main" ms-controller="problem_list">
|
<div class="container main" ms-controller="problem_list">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-9">
|
<div class="col-lg-9">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-lg-offset-9">
|
<div class="search-box">
|
||||||
<input type="text" class="form-control" placeholder="搜索题号,标题">
|
<form class="form-inline" onsubmit="return false;">
|
||||||
|
<div class="form-group-sm">
|
||||||
|
<input name="keyWord" class="form-control" placeholder="请输入关键词" ms-duplex="key_word">
|
||||||
|
<input type="submit" value="搜索" class="btn btn-primary" ms-click="getPage(1)">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -19,28 +25,33 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
{% for item in problems %}
|
||||||
<th scope="row"><a href="/problem/1/">1</a></th>
|
<tr>
|
||||||
<td><a href="/problem/1/">Mark</a></td>
|
<th scope="row"><a href="/problem/{{ item.id }}/">{{ item.id }}</a></th>
|
||||||
<td>Otto</td>
|
<td><a href="/problem/{{ item.id }}/">{{ item.title }}</a></td>
|
||||||
<td>@mdo</td>
|
<td>{{ item.difficulty }}</td>
|
||||||
</tr>
|
<td>{{ item|accepted_radio }}</td>
|
||||||
<tr>
|
</tr>
|
||||||
<th scope="row">2</th>
|
{% endfor %}
|
||||||
<td>Jacob</td>
|
|
||||||
<td>Thornton</td>
|
|
||||||
<td>@fat</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">3</th>
|
|
||||||
<td>Larry</td>
|
|
||||||
<td>the Bird</td>
|
|
||||||
<td>@twitter</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<nav>
|
||||||
|
<ul class="pager">
|
||||||
|
{% if previous_page %}
|
||||||
|
<li class="previous"><a
|
||||||
|
href="/problems/{{ previous_page }}/{% if keyword %}?keyword={{ keyword }}{% endif %}{% if tag %}?tag={{ tag }}{% endif %}">
|
||||||
|
<span aria-hidden="true">←</span> 上一页</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% if next_page %}
|
||||||
|
<li class="next"><a
|
||||||
|
href="/problems/{{ next_page }}/{% if keyword %}?keyword={{ keyword }}{% endif %}{% if tag %}?tag={{ tag }}{% endif %}">下一页 <span
|
||||||
|
aria-hidden="true">→</span></a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
<div class="panel panel-info">
|
<div class="panel panel-info">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
@@ -87,5 +98,5 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_block %}
|
{% block js_block %}
|
||||||
<script src="/static/js/app/oj/problem/problem_list.js"></script>
|
<script src="/static/js/app/oj/problem/problem_list.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -48,28 +48,28 @@
|
|||||||
<li><a href="/about/">关于</a></li>
|
<li><a href="/about/">关于</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||||
aria-expanded="false">
|
aria-expanded="false">
|
||||||
李扬
|
李扬
|
||||||
<span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="#">我的提交</a></li>
|
<li><a href="#">我的提交</a></li>
|
||||||
<li><a href="#">我的资料</a></li>
|
<li><a href="#">我的资料</a></li>
|
||||||
<li role="separator" class="divider"></li>
|
<li role="separator" class="divider"></li>
|
||||||
<li><a href="#">退出</a></li>
|
<li><a href="#">退出</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% else %}
|
{% else %}
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="/login/" class="dropdown-toggle">
|
<a href="/login/" class="dropdown-toggle">
|
||||||
登录
|
登录
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
14
utils/templatetags/problem.py
Normal file
14
utils/templatetags/problem.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
|
||||||
|
def get_problem_accepted_radio(problem):
|
||||||
|
if problem.total_accepted_number:
|
||||||
|
return int((problem.total_accepted_number * 100) / problem.total_submit_number)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
register.filter("accepted_radio", get_problem_accepted_radio)
|
||||||
Reference in New Issue
Block a user