基本完成创建题目页面

This commit is contained in:
virusdefender 2016-08-20 23:04:41 +08:00
parent 37f12b6bb2
commit 386a6dd173
12 changed files with 253 additions and 135 deletions

View File

@ -28,6 +28,14 @@
font-size: 16px;
}
.sub-label {
font-size: 12px;
display: inline-block;
max-width: 100%;
margin-bottom: 5px;
font-weight: bold;
}
</style>
<script>

View File

@ -31,7 +31,7 @@
<td>{{ user.email }}</td>
<td>{{ $t(adminType[user.admin_type]) }}</td>
<td>
<button class="btn-sm btn-info" v-on:click="edit(user.id)">{{ $t("adminUtils.edit") }}</button>
<button type="button" class="btn-sm btn-info" v-on:click="edit(user.id)">{{ $t("adminUtils.edit") }}</button>
<a target="_blank" href="/submissions/?user_id={{ user.id }}">
{{ $t("user.submission") }}
</a>

View File

@ -18,7 +18,7 @@
<td>{{ announcement.created_by.username }}</td>
<td>{{ $t(announcementStatus[announcement.visible?1:0]) }}</td>
<td>
<button class="btn-sm btn-info" v-on:click="edit(announcement.id)">{{ $t("adminUtils.edit") }}</button>
<button type="button" class="btn-sm btn-info" v-on:click="edit(announcement.id)">{{ $t("adminUtils.edit") }}</button>
</td>
</tr>
</table>

View File

@ -2,34 +2,35 @@
<div class="rows">
<back></back>
<h3>{{ $t("problem.createProblem") }}</h3>
<form v-on:submit="submit">
<div class="form-group col-md-12">
<label>{{ $t("adminUtils.title") }}</label>
<input type="text" class="form-control" maxlength="50" required>
<input type="text" class="form-control" maxlength="50" v-model="title" required>
</div>
<div class="form-group col-md-12">
<label>{{ $t("adminUtils.description") }}</label>
<simditor v-ref:problemdescription></simditor>
<simditor v-ref:problem-description></simditor>
</div>
<div class="col-md-3">
<div class="form-group">
<label>{{ $t("problem.timeLimit") }}</label>
<help name="timeLimit"></help>
<input type="number" class="form-control" required>
<input type="number" class="form-control" v-model="timeLimit" required>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>{{ $t("problem.memoryLimit") }}</label>
<help name="memoryLimit"></help>
<input type="number" class="form-control" required>
<input type="number" class="form-control" v-model="memoryLimit" required>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>{{ $t("problem.difficulty") }}</label>
<select class="form-control" required>
<select class="form-control" required v-model="difficulty">
<option value="1" selected="selected">{{ $t("problem.easy") }}</option>
<option value="2">{{ $t("problem.medium") }}</option>
<option value="3">{{ $t("problem.hard") }}</option>
@ -38,26 +39,45 @@
</div>
<div class="col-md-3 form-group">
<label>{{ $t("adminUtils.isVisible")}}</label><br>
<input type="checkbox">可见
<input type="checkbox" checked v-model="visible">可见
</div>
<div class="col-md-12">
<label>{{ $t("problem.tag") }}</label>
<tag-input :tag-list.sync="tagList"></tag-input>
</div>
<problem-sample :samples.sync="samples"></problem-sample>
<test-case-mgnt :mode="mode" :test-case-list="testCaseList"></test-case-mgnt>
<problem-sample :sample-list.sync="sampleList"></problem-sample>
<test-case-mgnt :mode="mode" :test-case-list="testCaseList" :special-judge="specialJudge"></test-case-mgnt>
<div class="col-md-12">
<label>Special Judge</label>
<code-mirror :selected-language-name="selectedLanguageName" :language-list="languageList"></code-mirror>
<special-judge :special-judge.sync="specialJudge" :language-list="languageList"
:selected-language.sync="specialJudgeLanguage"></special-judge>
</div>
<div class="col-md-12">
<label>{{ $t("problem.hint") }}</label>
<simditor></simditor>
</div>
<div class="col-md-12">
<label>{{ $t("problem.source") }}</label>
<div class="form-group">
<input type="text" class="form-control" list="problemSourceAutoCompleteList" v-model="source">
<datalist id="problemSourceAutoCompleteList">
<option value="{{ item }}" v-for="item in problemSourceAutoCompleteList"></option>
</datalist>
</div>
</div>
<div class="col-md-12">
<input type="submit" class="btn btn-primary btn-lg" value='{{ $t("adminUtils.submit") }}'>
</div>
</form>
</div>
</template>
<script>
import testCaseMgnt from "../utils/testCaseMgnt.vue"
import problemSample from "../utils/problemSample.vue"
import specialJudge from "./specialJudge.vue"
import back from "../utils/back.vue"
import simditor from "../utils/simditor.vue"
@ -69,12 +89,20 @@
export default({
data() {
return {
title: "",
timeLimit: 100,
memoryLimit: 128,
difficulty: "1",
visible: true,
tagList: ["1234", "呵呵哒"],
selectedLanguageName: "C",
languageList: [{name: "C", description: "xxxxxx"}],
samples: [{input: "", output: "", visible: true}],
sampleList: [{input: "", output: "", visible: true}],
mode: "ACM",
testCaseList: [{input_name: "1.in", output_name: "1.out"}]
testCaseList: [{input_name: "1.in", output_name: "1.out", score: 0}],
specialJudge: true,
languageList: [{name: "C", description: "xxxxxx"}],
specialJudgeLanguage: "C",
source: "",
problemSourceAutoCompleteList: []
}
},
components: {
@ -85,7 +113,40 @@
tagInput,
codeMirror,
help,
helpLink
helpLink,
specialJudge
},
methods: {
submit() {
if (!this.$refs.problemDescription.getContent().trim()) {
alert(this.$t("problem.problemDescriptionIsRequired"));
return false;
}
if (!this.tagList) {
alert(this.$t(""));
return false;
}
if (!this.testCaseList) {
}
if (this.specialJudge && !this.$refs.specialJudgeCode.getCode().trim()) {
}
var submitData = {
title: this.title,
description: this.$refs.problemDescription.getContent(),
timeLimit: this.timeLimit,
memoryLimit: this.memoryLimit,
difficulty: this.difficulty,
visible: this.visible,
sample_list: this.sample_list,
mode: this.mode,
};
return false;
}
}
})
</script>

View File

@ -28,7 +28,7 @@
<td>{{ problem.created_by.username }}</td>
<td>{{ $t(problemStatus[problem.visible?1:0]) }}</td>
<td>
<button class="btn-sm btn-info" v-on:click="edit(problem.id)">{{ $t("adminUtils.edit") }}</button>
<button type="button" class="btn-sm btn-info" v-on:click="edit(problem.id)">{{ $t("adminUtils.edit") }}</button>
</td>
</tr>
</table>

View File

@ -0,0 +1,78 @@
<template>
<div>
<label>Special Judge</label>
<div @click="switchSpecialJudge($event)">
<input type="checkbox" v-model="specialJudge"> <span class="sub-label">{{ $t("problem.turnOnSpecialJudge") }}</span>
</div>
<div v-if="specialJudge">
<code-mirror :selected-language="selectedLanguage" :language-list="languageList"></code-mirror>
</div>
<div class="col-md-12 test-special-judge">
<div class="form-group" v-if="specialJudge">
<input type="checkbox" v-model="testSpecialJudge">
<span class="sub-label">{{ $t("problem.testSpecialJudge") }}</span>
</div>
<div class="form-group" v-if="specialJudge && testSpecialJudge">
<textarea v-model="specialJudgeTestCase" class="form-control" rows="4"></textarea>
</div>
<div class="form-group" v-if="specialJudge && testSpecialJudge">
<button type="button" class="btn btn-primary">{{ $t("adminUtils.submit") }}</button>
</div>
</div>
<div class="col-md-12 test-special-jduge" v-if="specialJudge && testSpecialJudge">
<p class="sub-label">{{ $t("problem.specialJudgeTestResult") }}</p>
<p>{{ $t("adminUtils.CPUTime") }}: {{ CPUTime }} ms</p>
<p>{{ $t("adminUtils.memory") }}: {{ memory }} KB</p>
<p>{{ $t("problem.runResult") }}: {{ runResult }}</p>
<p v-if="output">{{ $t("problem.output") }}</p>
<pre v-if="output">{{ output }}</pre>
</div>
</div>
</template>
<script>
import codeMirror from "../utils/codeMirror.vue"
export default ({
props: {
specialJudge: {
type: Boolean,
required: true
},
selectedLanguage: {
type: String,
required: true,
},
languageList: {
type: Array,
required: true
}
},
data() {
return {
testSpecialJudge: true,
specialJudgeTestCase: "",
CPUTime: 0,
memory: 0,
runResult: "Loading",
output: ""
}
},
components: {
codeMirror
},
methods: {
switchSpecialJudge(e) {
confirm(this.$t("problem.switchSpecialJudge"), ()=> {}, ()=> {this.specialJudge = !this.specialJudge});
}
}
})
</script>
<style scoped>
.test-special-judge {
padding-top: 5px;
}
</style>

View File

@ -1,9 +0,0 @@
<template>
<div class="col-md-12">
<code-mirror></code-mirror>
</div>
</template>
<script>
import codeMirror from "../utils/codeMirror.vue"
</script>

View File

@ -1,18 +1,18 @@
<template>
<div>
<div>
<p>{{ $t("problem.chooseLanguage") }}</p>
<p class="sub-label">{{ $t("problem.chooseLanguage") }}</p>
<div id="language-radio">
<template v-for="language in languageList">
<span class="radio-inline">
<input type="radio" value="{{ language.name }}" name="language" v-model="selectedLanguageName">
<input type="radio" value="{{ language.name }}" name="language" v-model="selectedLanguage">
{{ language.name }} ({{ language.description }})
</span>
</template>
</div>
</div>
<div>
<p>{{ $t("problem.submitCode") }}</p>
<p class="sub-label">{{ $t("problem.submitCode") }}</p>
<textarea id="{{ editorId }}"></textarea>
</div>
</div>
@ -40,7 +40,7 @@
type: Array,
required: true,
},
selectedLanguageName: {
selectedLanguage: {
type: String,
required: true,
}
@ -59,14 +59,14 @@
attached() {
this.editor = CodeMirror.fromTextArea(document.getElementById(this.editorId), {
lineNumbers: true,
mode: getMime(this.selectedLanguageName),
mode: getMime(this.selectedLanguage),
indentUnit: 4,
matchBrackets: true
});
},
methods: {
setLanguage(languageName) {
this.selectedLanguageName = languageName;
setLanguage(language) {
this.selectedLanguage = languageName;
},
setCode(code) {
this.editor.setValue(code);
@ -75,7 +75,7 @@
return this.editor.getValue();
},
getLanguage() {
return this.selectedLanguageName;
return this.selectedLanguage;
}
}
})

View File

@ -1,17 +1,17 @@
<template>
<div class="col-md-12"><br>
<label>{{ $t("problem.sample") }}</label>
<button class="btn btn-primary btn-sm add-sample-btn" v-on:click="addSample">{{ $t("problem.addSample") }}
<button class="btn btn-primary btn-sm add-sample-btn" type="button" v-on:click="addSample">{{ $t("problem.addSample") }}
</button>
<div>
<div class="panel panel-default" v-for="sample in samples">
<div class="panel panel-default" v-for="sample in sampleList">
<div class="panel-heading">
<span class="panel-title">{{ $t("problem.sample") }} {{ $index + 1 }}</span>
<button class="btn btn-primary btn-sm" v-on:click="toggleSample($index)">
<button type="button" class="btn btn-primary btn-sm" v-on:click="toggleSample($index)">
{{ sample.visible?$t("problem.fold"):$t("problem.show") }}
</button>
<button class="btn btn-danger btn-sm" v-on:click="delSample($index)">
<button type="button" class="btn btn-danger btn-sm" v-on:click="delSample($index)">
{{ $t("adminUtils.delete") }}
</button>
</div>
@ -37,34 +37,21 @@
<script>
export default({
props: {
samples: {
sampleList: {
type: Array,
required: true
}
},
methods: {
setSample(samples) {
for(let sample of samples) {
sample[visible] = false;
}
this.samples = samples;
},
getSample() {
var samples = this.samples;
for(let sample of samples) {
delete sample.visible;
}
return samples;
},
addSample() {
this.samples.push({input: "", output: "", visible: true});
this.sampleList.push({input: "", output: "", visible: true});
},
toggleSample(index) {
this.samples[index].visible = !this.samples[index].visible;
this.sampleList[index].visible = !this.sampleList[index].visible;
},
delSample(index) {
confirm(this.$t("problem.deleteThisSample"), ()=> {
this.samples.splice(index, 1);
this.sampleList.splice(index, 1);
});
}
}

View File

@ -2,22 +2,22 @@
<div class="col-md-12">
<label>
{{ $t("problem.testCase") }}
<help-link :link="https://github.com/QingdaoU/OnlineJudge/wiki/%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E4%B8%8A%E4%BC%A0"></help-link>
<help-link link="https://github.com/QingdaoU/OnlineJudge/wiki/%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E4%B8%8A%E4%BC%A0"></help-link>
<a v-show="downloadURL" v-bind:href="downloadURL">{{ $t("adminUtils.download") }}</a>
</label>
<div>
<div class="form-group">
<p>{{ $t("problem.mode") }}</p>
<p class="sub-label">{{ $t("problem.mode") }}</p>
<div>
<span class="radio-inline"><input type="radio" name="mode" value="ACM" checked>{{ $t("problem.ACMMode") }}</span>
<span class="radio-inline"><input type="radio" name="mode" value="OI">{{ $t("problem.OIMode") }}</span>
<span class="radio-inline"><input type="radio" name="mode" value="ACM" v-model="mode" checked>{{ $t("problem.ACMMode") }}</span>
<span class="radio-inline"><input type="radio" name="mode" value="OI" v-model="mode">{{ $t("problem.OIMode") }}</span>
</div>
</div>
</div>
<div>
<p>{{ $t("problem.uploadProgress") }}</p>
<p class="sub-label">{{ $t("problem.uploadProgress") }}</p>
<div class="progress">
<div class="progress-bar progress-bar-striped" role="progressbar " aria-valuenow="{{ uploadProgress }}"
aria-valuemin="0"
@ -32,15 +32,14 @@
<tr>
<td>ID</td>
<td>{{ $t("adminUtils.input") }}</td>
<td>{{ $t("adminUtils.output") }}</td>
<td v-if="OIMode">{{ $t("problem.score") }}</td>
<td v-if="!specialJudge">{{ $t("adminUtils.output") }}</td>
<td v-if="mode == 'OI'">{{ $t("problem.score") }}</td>
</tr>
<tr v-for="testCase in testCaseList">
<td>{{ $index + 1 }}</td>
<td>{{ testCase.input_name }}</td>
<td>{{ testCase.output_name }}</td>
<td v-if="mode == 'OI'"><input class="score" v-model="testCase.score" type="number" min="1" required>
</td>
<td v-if="!specialJudge">{{ testCase.output_name }}</td>
<td v-if="mode == 'OI'"><input class="score" v-model="testCase.score" type="number" min="1" required></td>
</tr>
</table>
<div class="form-group">
@ -74,6 +73,10 @@
mode: {
type: String,
required: true
},
specialJudge: {
type: Boolean,
required: true
}
},
data() {
@ -92,24 +95,6 @@
uploadError(f, reason){
this.uploadProgress = 0;
alert(this.$t("request.error"));
},
setTestCase(mode, testCaseList) {
// attr must be set firstly so vue can track it's changes
if (this.mode == "OI") {
for (let item of testCaseList) {
item.score = 0;
}
}
this.testCaseList = testCaseList;
},
getTestCase() {
var testCaseList = this.testCaseList;
if (this.mode != "OI") {
for (let item of testCaseList) {
delete item.score;
}
}
return {testCaseList: testCaseList, mode: this.mode == "OI"};
}
}
})

View File

@ -77,7 +77,17 @@ export default {
easy: "简单",
difficulty: "难度",
chooseLanguage: "选择语言",
submitCode: "提交代码"
submitCode: "提交代码",
switchMode: "如果更换题目模式,需要重新上传测试用例",
switchSpecialJudge: "如果切换判题模式,需要重新上传测试用例",
turnOnSpecialJudge: "使用Special Judge",
testSpecialJudge: "测试Special Judge代码",
specialJudgeTestResult: "Special Judge测试运行结果",
runResult: "运行结果",
output: "输出",
hint: "提示",
source: "题目来源",
problemDescriptionIsRequired: "请填写题目描述"
},
tag: {
hint: "回车创建标签"
@ -114,7 +124,9 @@ export default {
chooseFile: "选择文件",
unsupportedBrowserWarningMsg: "当前网页 <strong>不支持</strong> 你正在使用的浏览器, 为了正常的访问,请到 <a href=\"http://browsehappy.com/\"> 升级你的浏览器</a>"
unsupportedBrowserWarningMsg: "当前网页 <strong>不支持</strong> 你正在使用的浏览器, 为了正常的访问,请到 <a href=\"http://browsehappy.com/\"> 升级你的浏览器</a>",
CPUTime: "CPU时间",
memory: "内存"
},
help: {
timeLimit: "1-1000ms",

View File

@ -125,29 +125,25 @@ window.alert = function bootboxAlert(content) {
// override window.confirm
window.confirm = function bootboxConfirm(content, okCallback, cancelCallback) {
bootbox.dialog ({
var config = {
message: content,
title: locale[lang].alert.confirm,
buttons: {
cancel: {
label: locale[lang].alert.cancel,
className: "btn-success",
callback: function() {
if(cancelCallback) {
return cancelCallback;
}
else {
return function(){};
}
}
className: "btn-success"
},
main: {
label: locale[lang].alert.OK,
className: "btn-danger",
className: "btn-warning",
callback: okCallback
}
}
})
};
if (cancelCallback) {
config.buttons.cancel.callback = cancelCallback;
}
bootbox.dialog (config)
};
router.redirect({"/user": "/user/1"});