|
|
|
|
<% this.title = contest.id ? '编辑比赛' : '新建比赛' %>
|
|
|
|
|
<% include header %>
|
|
|
|
|
<% include monaco-editor %>
|
|
|
|
|
<div class="padding" id="edit_contest">
|
|
|
|
|
<form action="<%= syzoj.utils.makeUrl(['contest', contest.id, 'edit']) %>" method="post" id="form">
|
|
|
|
|
<div class="ui form">
|
|
|
|
|
<div class="field">
|
|
|
|
|
<label>比赛名称</label>
|
|
|
|
|
<input type="text" name="title" value="<%= contest.title %>">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<label>比赛描述</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div id="subtitle" class="editor editor-with-border" style="height: 100px; width: 100%; margin-bottom: 1em; ">
|
|
|
|
|
<%- this.showLoadingEditor(); %>
|
|
|
|
|
</div>
|
|
|
|
|
<input type="hidden" name="subtitle">
|
|
|
|
|
<div class="ui form">
|
|
|
|
|
<div class="field">
|
|
|
|
|
<label>试题列表</label>
|
|
|
|
|
<!-- <% include problem_table %>-->
|
|
|
|
|
<input type="input" hidden name="problems" v-model="calcProblemsValue" />
|
|
|
|
|
<el-tag @close="handleClose(item)" closable v-for="item in userselectarray" style="margin-right:5px">#{{item.id}}{{item.title}}</el-tag>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<el-table
|
|
|
|
|
ref="multipleTable"
|
|
|
|
|
:data="datas"
|
|
|
|
|
tooltip-effect="dark"
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
@select="handleSelectionChange"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column
|
|
|
|
|
type="selection"
|
|
|
|
|
width="55">
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column
|
|
|
|
|
prop="id"
|
|
|
|
|
label="题目id">
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column
|
|
|
|
|
prop="title"
|
|
|
|
|
label="题目标题">
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
<el-pagination
|
|
|
|
|
@current-change="handlePageChange"
|
|
|
|
|
layout="prev, pager, next"
|
|
|
|
|
:current-page.sync="currentPage"
|
|
|
|
|
:total="max">
|
|
|
|
|
</el-pagination>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<label>比赛管理员</label>
|
|
|
|
|
<select class="ui fluid search dropdown" multiple="" id="search_admins" name="admins">
|
|
|
|
|
<% for (let admin of admins) { %>
|
|
|
|
|
<option value="<%= admin.id %>" selected><%= admin.username %></option>
|
|
|
|
|
<% } %>
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="inline fields">
|
|
|
|
|
<label>赛制</label>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<div class="ui radio checkbox">
|
|
|
|
|
<input <% if (contest.id) { %>disabled <% } %>type="radio" name="type" id="type-noi" value="noi"<% if (contest.type === 'noi') { %> checked="checked"<% } %>>
|
|
|
|
|
<label for="type-noi">NOI</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<div class="ui radio checkbox">
|
|
|
|
|
<input <% if (contest.id) { %>disabled <% } %>type="radio" name="type" id="type-ioi" value="ioi"<% if (contest.type === 'ioi') { %> checked="checked"<% } %>>
|
|
|
|
|
<label for="type-ioi">IOI</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<div class="ui radio checkbox">
|
|
|
|
|
<input <% if (contest.id) { %>disabled <% } %>type="radio" name="type" id="type-acm" value="acm"<% if (contest.type === 'acm') { %> checked="checked"<% } %>>
|
|
|
|
|
<label for="type-acm">ICPC</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<label>排行参数(格式:<code>{ "题目 ID": 分值倍数 }</code>)</label>
|
|
|
|
|
<input type="text" name="ranking_params" value="<%= contest.ranklist ? JSON.stringify(contest.ranklist.ranking_params) : '' %>">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<label>比赛公告</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div id="information" class="editor editor-with-border" style="height: 100px; width: 100%; margin-bottom: 1em; ">
|
|
|
|
|
<%- this.showLoadingEditor(); %>
|
|
|
|
|
</div>
|
|
|
|
|
<input type="hidden" name="information">
|
|
|
|
|
<div class="ui form">
|
|
|
|
|
<div class="field">
|
|
|
|
|
<label>开始时间</label>
|
|
|
|
|
<input type="text" name="start_time" value="<%= syzoj.utils.formatDate(contest.start_time || syzoj.utils.getCurrentDate()) %>">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="field">
|
|
|
|
|
<label>结束时间</label>
|
|
|
|
|
<input type="text" name="end_time" value="<%= syzoj.utils.formatDate(contest.end_time || syzoj.utils.getCurrentDate()) %>">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="inline field">
|
|
|
|
|
<label class="ui header">公开</label>
|
|
|
|
|
<div class="ui toggle checkbox">
|
|
|
|
|
<input type="checkbox"<% if (contest.is_public) { %> checked<% } %> name="is_public">
|
|
|
|
|
<label><span style="visibility: hidden; "> </span></label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="inline field">
|
|
|
|
|
<label class="ui header">隐藏统计信息</label>
|
|
|
|
|
<div class="ui toggle checkbox">
|
|
|
|
|
<input type="checkbox"<% if (contest.hide_statistics) { %> checked<% } %> name="hide_statistics">
|
|
|
|
|
<label><span style="visibility: hidden; "> </span></label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="text-align: center; "><button id="submit_button" type="submit" class="ui disabled labeled icon blue button"><i class="ui edit icon"></i>提交</button></div>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
<script>
|
|
|
|
|
new window.Vue({
|
|
|
|
|
el:'#edit_contest',
|
|
|
|
|
data: {
|
|
|
|
|
userselectarray: [],
|
|
|
|
|
allproblemList:[],
|
|
|
|
|
datas: [],
|
|
|
|
|
currentPage:1,
|
|
|
|
|
max: 0,
|
|
|
|
|
arrayItem: null
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
this.loadProblem();
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
loadProblem() {
|
|
|
|
|
fetch('/api/pagination/allproblem').then(res => res.json()).then(data => {
|
|
|
|
|
this.max = parseInt(data.problemInfo.length);
|
|
|
|
|
this.allproblemList = data.problemInfo;
|
|
|
|
|
this.datas = data.problemInfo.slice(0,10);
|
|
|
|
|
this.loadData();
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
loadData() {
|
|
|
|
|
let id = <%= contest_id %>;
|
|
|
|
|
fetch(`/api/contest/problem/${id}`).then(res=> res.json()).then(subitem => {
|
|
|
|
|
const originUserselectarray = subitem.problems.map((item) =>{
|
|
|
|
|
return {
|
|
|
|
|
id: item.id,
|
|
|
|
|
title: item.title
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
const userselectarrayId = originUserselectarray.map(item=>item.id);
|
|
|
|
|
const userSelectArray = this.allproblemList.filter((item) => {
|
|
|
|
|
return userselectarrayId.includes(item.id);
|
|
|
|
|
})
|
|
|
|
|
this.toggleSelection(userSelectArray);
|
|
|
|
|
this.userselectarray = userSelectArray;
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
handleClose(tag) {
|
|
|
|
|
const deleteItem = this.userselectarray.splice(this.userselectarray.indexOf(tag), 1);
|
|
|
|
|
this.toggleSelection(deleteItem)
|
|
|
|
|
},
|
|
|
|
|
getProblemPagination(page) {
|
|
|
|
|
let that = this;
|
|
|
|
|
this.datas = this.allproblemList.slice((page - 1)*10, (page - 1)*10+10);
|
|
|
|
|
this.$nextTick(function(){
|
|
|
|
|
that.toggleSelection(that.userselectarray);
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
selectProblem: function(array) {
|
|
|
|
|
this.toggleSelection(array)
|
|
|
|
|
},
|
|
|
|
|
toggleSelection(rows) {
|
|
|
|
|
if (rows) {
|
|
|
|
|
rows.forEach(row => {
|
|
|
|
|
this.$refs.multipleTable.toggleRowSelection(row);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.$refs.multipleTable.clearSelection();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
handlePageChange(page){
|
|
|
|
|
this.selectProblem(this.userselectarray);
|
|
|
|
|
this.getProblemPagination(page);
|
|
|
|
|
},
|
|
|
|
|
handleSelectionChange(val, row){
|
|
|
|
|
const multipleSelectionId = this.userselectarray.map(item => item.id);
|
|
|
|
|
|
|
|
|
|
if (multipleSelectionId.includes(row.id)) {
|
|
|
|
|
this.userselectarray.splice(this.userselectarray.indexOf(row), 1)
|
|
|
|
|
} else {
|
|
|
|
|
this.userselectarray.push(row);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
disableCheckbox: function(row) {
|
|
|
|
|
if (this.disabledidarray) {
|
|
|
|
|
return !this.disabledidarray.includes(row.id);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
calcProblemsValue:function(){
|
|
|
|
|
console.log(this.userselectarray.map(item=>item.id));
|
|
|
|
|
return this.userselectarray.map(item=>item.id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
var editors = {
|
|
|
|
|
subtitle: { defaultValue: <%- serializejs(contest.subtitle) %> },
|
|
|
|
|
information: { defaultValue: <%- serializejs(contest.information) %> }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.onEditorLoaded(function () {
|
|
|
|
|
for (var name in editors) {
|
|
|
|
|
var editor = editors[name];
|
|
|
|
|
var editorElement = document.getElementById(name);
|
|
|
|
|
var input = document.getElementsByName(name)[0];
|
|
|
|
|
editor.editor = window.createMarkdownEditor(editorElement, editor.defaultValue, input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$('#submit_button').removeClass('disabled');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$(function () {
|
|
|
|
|
$('#search_admins')
|
|
|
|
|
.dropdown({
|
|
|
|
|
debug: true,
|
|
|
|
|
apiSettings: {
|
|
|
|
|
url: '/api/v2/search/users/{query}',
|
|
|
|
|
onResponse: function (response) {
|
|
|
|
|
var a = $('#search_admins').val().map(function (x) { return parseInt(x) });
|
|
|
|
|
if (response.results) {
|
|
|
|
|
response.results = response.results.filter(function(x){ return !a.includes(parseInt(x.value))});
|
|
|
|
|
}
|
|
|
|
|
return response;
|
|
|
|
|
},
|
|
|
|
|
cache: false
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
$('#search_problems')
|
|
|
|
|
.dropdown({
|
|
|
|
|
debug: true,
|
|
|
|
|
apiSettings: {
|
|
|
|
|
url: '/api/v2/search/problems/{query}',
|
|
|
|
|
onResponse: function (response) {
|
|
|
|
|
var a = $('#search_problems').val().map(function (x) { return parseInt(x) });
|
|
|
|
|
if (response.results) {
|
|
|
|
|
response.results = response.results.filter(function(x) {return !a.includes(parseInt(x.value));});
|
|
|
|
|
}
|
|
|
|
|
return response;
|
|
|
|
|
},
|
|
|
|
|
cache: false
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
<% include footer %>
|