Merge pull request #42 from QingdaoU/feature/update_1

Feature/update 1
This commit is contained in:
李扬 2019-03-26 09:58:34 +08:00 committed by GitHub
commit 74644d2a57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 186 additions and 27 deletions

View File

@ -8,6 +8,9 @@ export const m = {
Judge_Server: 'Judge Server',
Prune_Test_Case: 'Prune Test Case',
Problem: 'Problem',
FromFile: 'From File',
ToFile: 'To File',
ShareSubmission: 'Share Submission',
Problem_List: 'Problem List',
Create_Problem: 'Create Problem',
Export_Import_Problem: 'Export Or Import Problem',
@ -32,7 +35,7 @@ export const m = {
General_Announcement: 'Announcement',
Announcement_Title: 'Title',
Announcement_Content: 'Conten',
Announcement_Status: 'Status',
Announcement_visible: 'Visible',
// Conf.vue
SMTP_Config: 'SMTP Config',
Server: 'Server',
@ -77,6 +80,9 @@ export const m = {
SPJ_language: 'SPJ language',
Compile: 'Compile',
TestCase: 'TestCase',
IOMode: 'IO Mode',
InputFileName: 'Input File Name',
OutputFileName: 'Output File Name',
Type: 'Type',
Input: 'Input',
Output: 'Output',

View File

@ -8,6 +8,9 @@ export const m = {
Judge_Server: '判题服务器',
Prune_Test_Case: '测试用例',
Problem: '问题',
FromFile: '读取文件',
ToFile: '写入文件',
ShareSubmission: '分享提交',
Problem_List: '问题列表',
Create_Problem: '增加题目',
Export_Import_Problem: '导入导出题目',
@ -32,7 +35,7 @@ export const m = {
General_Announcement: '公告',
Announcement_Title: '标题',
Announcement_Content: '内容',
Announcement_Status: '状态',
Announcement_visible: '是否可见',
// Conf.vue
SMTP_Config: 'SMTP Config',
Server: '服务器',
@ -77,6 +80,9 @@ export const m = {
SPJ_language: 'SPJ language',
Compile: '编译',
TestCase: '测试用例',
IOMode: 'IO 类型',
InputFileName: '输入文件名',
OutputFileName: '输出文件名',
Type: '测试类型',
Input: '输入',
Output: '输出',

View File

@ -8,6 +8,9 @@ export const m = {
Judge_Server: 'Judge 伺服器',
Prune_Test_Case: '測資',
Problem: '試題',
FromFile: '讀取檔案',
ToFile: '寫入檔案',
ShareSubmission: '分享提交',
Problem_List: '試題列表',
Create_Problem: '增加題目',
Export_Import_Problem: '匯入匯出題目',
@ -32,7 +35,7 @@ export const m = {
General_Announcement: '公告',
Announcement_Title: '標題',
Announcement_Content: '內容',
Announcement_Status: '狀態',
Announcement_visible: '是否可見',
// Conf.vue
SMTP_Config: 'SMTP 設定',
Server: '伺服器',
@ -77,6 +80,9 @@ export const m = {
SPJ_language: 'SPJ language',
Compile: '編譯',
TestCase: '測資',
IOMode: 'IO 類型',
InputFileName: '輸入檔名',
OutputFileName: '輸出檔名',
Type: '測試類型',
Input: '輸入',
Output: '輸出',

View File

@ -7,13 +7,14 @@
import 'tar-simditor/styles/simditor.css'
import 'tar-simditor-markdown'
import 'tar-simditor-markdown/styles/simditor-markdown.css'
import './simditor-file-upload'
export default {
name: 'Simditor',
props: {
toolbar: {
type: Array,
default: () => ['title', 'bold', 'italic', 'underline', 'fontScale', 'color', 'ol', 'ul', '|', 'link', 'image', 'hr', '|', 'indent', 'outdent', 'alignment', '|', 'markdown']
default: () => ['title', 'bold', 'italic', 'underline', 'fontScale', 'color', 'ol', 'ul', '|', 'link', 'image', 'uploadfile', 'hr', '|', 'indent', 'outdent', 'alignment', '|', 'markdown']
},
value: {
type: String,
@ -32,7 +33,7 @@
textarea: this.$refs.editor,
toolbar: this.toolbar,
pasteImage: true,
markdown: true,
markdown: false,
upload: {
url: '/api/admin/upload_image/',
params: null,

View File

@ -0,0 +1,85 @@
/* eslint-disable */
import Simditor from 'tar-simditor'
import * as $ from 'jquery'
var UploadFile,
__hasProp = {}.hasOwnProperty,
__extends = function (child, parent) {
for (var key in parent) {
if (__hasProp.call(parent, key)) child[key] = parent[key];
}
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
},
__slice = [].slice;
UploadFile = (function (_super) {
__extends(UploadFile, _super);
UploadFile.i18n = {
'zh-CN': {
uploadfile: '上传文件'
},
'en-US': {
uploadfile: 'upload file'
}
};
UploadFile.prototype.name = 'uploadfile';
UploadFile.prototype.icon = 'upload';
function UploadFile() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
UploadFile.__super__.constructor.apply(this, args);
this._initUpload();
}
UploadFile.prototype._initUpload = function () {
this.input = $('<input />', {
type: 'file',
style: 'position:absolute;top:0;right:0;height:100%;width:100%;opacity:0;filter:alpha(opacity=0);cursor:pointer;'
}).prependTo(this.el)
var _this = this;
this.el.on('click mousedown', 'input[type=file]', function (e) {
return e.stopPropagation();
}).on('change', 'input[type=file]', function (e) {
var formData = new FormData();
formData.append('file', this.files[0]);
$.ajax({
url: '/api/admin/upload_file',
type: 'POST',
cache: false,
data: formData,
processData: false,
contentType: false
}).done(function (res) {
if (!res.success) {
alert("upload file failed")
} else {
let link = '<a target="_blank" className="simditor-attach-link" href="' + res.file_path + '">' + res.file_name + '</a>'
_this.editor.setValue(_this.editor.getValue() + link)
}
}).fail(function (res) {
alert("upload file failed")
});
});
}
return UploadFile;
})(Simditor.Button);
Simditor.Toolbar.addButton(UploadFile);

View File

@ -84,7 +84,7 @@
<Simditor v-model="announcement.content"></Simditor>
</el-form-item>
<div class="visible-box">
<span>{{$t('m.Announcement_Status')}}</span>
<span>{{$t('m.Announcement_visible')}}</span>
<el-switch
v-model="announcement.visible"
active-text=""

View File

@ -26,9 +26,7 @@
<el-col :span="24">
<el-form-item label="TLS">
<el-switch
v-model="smtp.tls"
active-color="#13ce66"
inactive-color="#ff4949">
v-model="smtp.tls">
</el-switch>
</el-form-item>
</el-col>

View File

@ -231,9 +231,7 @@
<el-col :span="8">
<el-form-item :label="$t('m.Is_Disabled')">
<el-switch
v-model="user.is_disabled"
active-text=""
inactive-text="">
v-model="user.is_disabled">
</el-switch>
</el-form-item>
</el-col>
@ -326,7 +324,7 @@
})
},
deleteUsers (ids) {
this.$confirm('Sure to delete the user?', 'confirm', {
this.$confirm('Sure to delete the user? The associated resources created by this user will be deleted as well, like problem, contest, announcement, etc.', 'confirm', {
type: 'warning'
}).then(() => {
api.deleteUsers(ids.join(',')).then(res => {

View File

@ -6,7 +6,7 @@
<el-row :gutter="20">
<el-col :span="6">
<el-form-item prop="_id" :label="$t('m.Display_ID')"
:required="this.routeName === 'create-contest-problem' || this.routeName === 'edit-contet-problem'">
:required="this.routeName === 'create-contest-problem' || this.routeName === 'edit-contest-problem'">
<el-input :placeholder="$t('m.Display_ID')" v-model="problem._id"></el-input>
</el-form-item>
</el-col>
@ -57,7 +57,7 @@
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="6">
<el-col :span="4">
<el-form-item :label="$t('m.Visible')">
<el-switch
v-model="problem.visible"
@ -66,6 +66,15 @@
</el-switch>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item :label="$t('m.ShareSubmission')">
<el-switch
v-model="problem.share_submission"
active-text=""
inactive-text="">
</el-switch>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="Tag" :error="error.tags" required>
<span class="tags">
@ -177,7 +186,7 @@
</Accordion>
</el-form-item>
<el-row :gutter="20">
<el-col :span="6">
<el-col :span="4">
<el-form-item :label="$t('m.Type')">
<el-radio-group v-model="problem.rule_type" :disabled="disableRuleType">
<el-radio label="ACM">ACM</el-radio>
@ -185,7 +194,7 @@
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="6">
<el-form-item :label="$t('m.TestCase')" :error="error.testcase">
<el-upload
action="/api/admin/test_case"
@ -199,6 +208,26 @@
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item :label="$t('m.IOMode')">
<el-radio-group v-model="problem.io_mode.io_mode">
<el-radio label="Standard IO">Standard IO</el-radio>
<el-radio label="File IO">File IO</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="4" v-if="problem.io_mode.io_mode == 'File IO'">
<el-form-item :label="$t('m.InputFileName')" required>
<el-input type="text" v-model="problem.io_mode.input"></el-input>
</el-form-item>
</el-col>
<el-col :span="4" v-if="problem.io_mode.io_mode == 'File IO'">
<el-form-item :label="$t('m.OutputFileName')" required>
<el-input type="text" v-model="problem.io_mode.output"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-table
:data="problem.test_case_score"
@ -261,10 +290,12 @@
mode: '',
contest: {},
problem: {
languages: []
languages: [],
io_mode: {'io_mode': 'Standard IO', 'input': 'input.txt', 'output': 'output.txt'}
},
reProblem: {
languages: []
languages: [],
io_mode: {'io_mode': 'Standard IO', 'input': 'input.txt', 'output': 'output.txt'}
},
testCaseUploaded: false,
allLanguage: {},
@ -301,6 +332,7 @@
memory_limit: 256,
difficulty: 'Low',
visible: true,
share_submission: false,
tags: [],
languages: [],
template: {},
@ -313,7 +345,8 @@
test_case_score: [],
rule_type: 'ACM',
hint: '',
source: ''
source: '',
io_mode: {'io_mode': 'Standard IO', 'input': 'input.txt', 'output': 'output.txt'}
}
let contestID = this.$route.params.contestId
if (contestID) {
@ -438,7 +471,7 @@
let fileList = response.data.info
for (let file of fileList) {
file.score = (100 / fileList.length).toFixed(0)
if (this.problem.spj) {
if (!file.output_name && this.problem.spj) {
file.output_name = '-'
}
}

View File

@ -197,7 +197,7 @@
})
},
deleteProblem (id) {
this.$confirm('You can only delete the problem that doesn\'t have submissions, continue?', 'Delete Problem', {
this.$confirm('Sure to delete this problem? The associated submissions will be deleted as well.', 'Delete Problem', {
type: 'warning'
}).then(() => {
let funcName = this.routeName === 'problem-list' ? 'deleteProblem' : 'deleteContestProblem'

View File

@ -13,6 +13,12 @@
<Button icon="refresh" @click="onResetClick"></Button>
</Tooltip>
<Tooltip content="Upload file" placement="top" style="margin-left: 10px">
<Button icon="upload" @click="onUploadFile"></Button>
</Tooltip>
<input type="file" id="file-uploader" style="display: none" @change="onUploadFileDone">
</div>
</Col>
<Col :span=12>
@ -90,7 +96,7 @@
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
//
styleSelectedText: true,
lineWrapping: false,
lineWrapping: true,
highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: true}
},
mode: {
@ -128,6 +134,20 @@
},
onResetClick () {
this.$emit('resetCode')
},
onUploadFile () {
document.getElementById('file-uploader').click()
},
onUploadFileDone () {
let f = document.getElementById('file-uploader').files[0]
let fileReader = new window.FileReader()
let self = this
fileReader.onload = function (e) {
var text = e.target.result
self.editor.setValue(text)
document.getElementById('file-uploader').value = ''
}
fileReader.readAsText(f, 'UTF-8')
}
},
computed: {

View File

@ -8,10 +8,10 @@
<p class="title">{{$t('m.Description')}}</p>
<p class="content" v-html=problem.description></p>
<!-- {{$t('m.music')}} -->
<p class="title">{{$t('m.Input')}}</p>
<p class="title">{{$t('m.Input')}} <span v-if="problem.io_mode.io_mode=='File IO'">({{$t('m.FromFile')}}: {{ problem.io_mode.input }})</span></p>
<p class="content" v-html=problem.input_description></p>
<p class="title">{{$t('m.Output')}}</p>
<p class="title">{{$t('m.Output')}} <span v-if="problem.io_mode.io_mode=='File IO'">({{$t('m.ToFile')}}: {{ problem.io_mode.output }})</span></p>
<p class="content" v-html=problem.output_description></p>
<div v-for="(sample, index) of problem.samples" :key="index">
@ -147,6 +147,11 @@
<li>
<p>{{$t('m.Memory_Limit')}}</p>
<p>{{problem.memory_limit}}MB</p></li>
<li>
<li>
<p>{{$t('m.IOMode')}}</p>
<p>{{problem.io_mode.io_mode}}</p>
</li>
<li>
<p>{{$t('m.Created')}}</p>
<p>{{problem.created_by.username}}</p></li>
@ -242,7 +247,8 @@
created_by: {
username: ''
},
tags: []
tags: [],
io_mode: {'io_mode': 'Standard IO'}
},
pie: pie,
largePie: largePie,

View File

@ -134,7 +134,7 @@
let columns = baseColumn
if (data.info && data.info.data && !this.isConcat) {
// score exist means the submission is OI problem submission
if (data.info.data[0].score) {
if (data.info.data[0].score !== undefined) {
this.isConcat = true
columns = columns.concat(scoreColumn)
}