Browse Source

Add contest admin support.

pull/6/head
t123yh 7 years ago
parent
commit
552d684c04
  1. 4
      models/contest.js
  2. 31
      modules/api_v2.js
  3. 13
      modules/contest.js
  4. 2
      views/contest.ejs
  5. 23
      views/contest_edit.ejs

4
models/contest.js

@ -46,6 +46,7 @@ let model = db.define('contest', {
information: { type: Sequelize.TEXT }, information: { type: Sequelize.TEXT },
problems: { type: Sequelize.TEXT }, problems: { type: Sequelize.TEXT },
admins: { type: Sequelize.TEXT },
ranklist_id: { ranklist_id: {
type: Sequelize.INTEGER, type: Sequelize.INTEGER,
@ -76,6 +77,7 @@ class Contest extends Model {
title: '', title: '',
subtitle: '', subtitle: '',
problems: '', problems: '',
admins: '',
information: '', information: '',
type: 'noi', type: 'noi',
start_time: 0, start_time: 0,
@ -92,7 +94,7 @@ class Contest extends Model {
} }
async isSupervisior(user) { async isSupervisior(user) {
return user && (user.is_admin || this.holder_id === user.id); return user && (user.is_admin || this.holder_id === user.id || this.admins.split('|').includes(user.id.toString()));
} }
allowedSeeingOthers() { allowedSeeingOthers() {

31
modules/api_v2.js

@ -19,6 +19,37 @@
'use strict'; 'use strict';
app.get('/api/v2/search/users/:keyword*?', async (req, res) => {
try {
let User = syzoj.model('user');
let keyword = req.params.keyword || '';
let conditions = [];
const uid = parseInt(keyword);
if (uid != null && !isNaN(uid)) {
conditions.push({ id: uid });
}
if (keyword != null && String(keyword).length >= 2) {
conditions.push({ username: { like: `%${req.params.keyword}%` } });
}
if (conditions.length === 0) {
res.send({ success: true, results: [] });
} else {
let users = await User.query(null, {
$or: conditions
}, [['username', 'asc']]);
let result = [];
result = users.map(x => ({ name: `${x.username}`, value: x.id, url: syzoj.utils.makeUrl(['user', x.id]) }));
res.send({ success: true, results: result });
}
} catch (e) {
syzoj.log(e);
res.send({ success: false });
}
});
app.get('/api/v2/search/problems/:keyword*?', async (req, res) => { app.get('/api/v2/search/problems/:keyword*?', async (req, res) => {
try { try {
let Problem = syzoj.model('problem'); let Problem = syzoj.model('problem');

13
modules/contest.js

@ -63,12 +63,14 @@ app.get('/contest/:id/edit', async (req, res) => {
contest.id = 0; contest.id = 0;
} }
let problems = []; let problems = [], admins = [];
if (contest.problems) problems = await contest.problems.split('|').mapAsync(async id => await Problem.fromID(id)); if (contest.problems) problems = await contest.problems.split('|').mapAsync(async id => await Problem.fromID(id));
if (contest.admins) admins = await contest.admins.split('|').mapAsync(async id => await User.fromID(id));
res.render('contest_edit', { res.render('contest_edit', {
contest: contest, contest: contest,
problems: problems problems: problems,
admins: admins
}); });
} catch (e) { } catch (e) {
syzoj.log(e); syzoj.log(e);
@ -103,6 +105,7 @@ app.post('/contest/:id/edit', async (req, res) => {
contest.subtitle = req.body.subtitle; contest.subtitle = req.body.subtitle;
if (!Array.isArray(req.body.problems)) req.body.problems = [req.body.problems]; if (!Array.isArray(req.body.problems)) req.body.problems = [req.body.problems];
contest.problems = req.body.problems.join('|'); contest.problems = req.body.problems.join('|');
contest.admins = req.body.admins.join('|');
contest.information = req.body.information; contest.information = req.body.information;
contest.start_time = syzoj.utils.parseDate(req.body.start_time); contest.start_time = syzoj.utils.parseDate(req.body.start_time);
contest.end_time = syzoj.utils.parseDate(req.body.end_time); contest.end_time = syzoj.utils.parseDate(req.body.end_time);
@ -223,9 +226,13 @@ app.get('/contest/:id/ranklist', async (req, res) => {
try { try {
let contest_id = parseInt(req.params.id); let contest_id = parseInt(req.params.id);
let contest = await Contest.fromID(contest_id); let contest = await Contest.fromID(contest_id);
const curUser = res.locals.user;
if (!contest) throw new ErrorMessage('无此比赛。'); if (!contest) throw new ErrorMessage('无此比赛。');
if (!await contest.isAllowedSeeResultBy(res.locals.user)) throw new ErrorMessage('您没有权限进行此操作。'); if ([contest.allowedSeeingResult() && contest.allowedSeeingOthers(),
contest.isEnded(),
contest.isSupervisior(curUser)].every(x => !x))
throw new ErrorMessage('您没有权限进行此操作。');
await contest.loadRelationships(); await contest.loadRelationships();

2
views/contest.ejs

@ -71,7 +71,7 @@
<tr> <tr>
<td class="center aligned" style="white-space: nowrap; "> <td class="center aligned" style="white-space: nowrap; ">
<% if (problem.judge_id) { %> <% if (problem.judge_id) { %>
<a href="<%= syzoj.utils.makeUrl(['submission', problem.judge_id]) %>"> <a href="<%= syzoj.utils.makeUrl(['contest', 'submission', problem.judge_id]) %>">
<% if (typeof problem.status === 'string') { %> <% if (typeof problem.status === 'string') { %>
<span class="status <%= problem.status.toLowerCase().split(' ').join('_') %>"> <span class="status <%= problem.status.toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(problem.status)] || 'remove' %> icon"></i> <i class="<%= icon[getStatusMeta(problem.status)] || 'remove' %> icon"></i>

23
views/contest_edit.ejs

@ -18,6 +18,14 @@
<% } %> <% } %>
</select> </select>
</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"> <div class="inline fields">
<label>赛制</label> <label>赛制</label>
<div class="field"> <div class="field">
@ -62,6 +70,21 @@
</form> </form>
<script> <script>
$(function () { $(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(x => !a.includes(parseInt(x.value)));
}
return response;
},
cache: false
}
});
$('#search_problems') $('#search_problems')
.dropdown({ .dropdown({
debug: true, debug: true,

Loading…
Cancel
Save