From 1227acf47a4492658e41830c7b3444bebb669896 Mon Sep 17 00:00:00 2001
From: Baoshuo
Date: Sun, 23 Oct 2022 20:39:11 +0800
Subject: [PATCH] refactor(web/contest): contest manage v2 and contest
confirmation
---
web/app/controllers/add_contest.php | 40 +-
web/app/controllers/contest_confirmation.php | 77 ++
web/app/controllers/contest_inside.php | 25 +-
web/app/controllers/contest_manage.php | 889 +++++++++++++------
web/app/controllers/contest_members.php | 24 +-
web/app/controllers/contest_registration.php | 69 +-
web/app/controllers/contests.php | 16 +-
web/app/controllers/list_edit.php | 2 +-
web/app/controllers/problem.php | 24 +-
web/app/libs/uoj-contest-lib.php | 1 +
web/app/route.php | 3 +-
web/js/uoj.js | 2 +-
12 files changed, 842 insertions(+), 330 deletions(-)
create mode 100644 web/app/controllers/contest_confirmation.php
diff --git a/web/app/controllers/add_contest.php b/web/app/controllers/add_contest.php
index c9e8699..11b2e13 100644
--- a/web/app/controllers/add_contest.php
+++ b/web/app/controllers/add_contest.php
@@ -16,7 +16,23 @@
$time_form = new UOJForm('time');
$time_form->addVInput(
'name', 'text', '比赛标题', 'New Contest',
- function($str) {
+ function($name, &$vdata) {
+ if ($name == '') {
+ return '标题不能为空';
+ }
+
+ if (strlen($name) > 100) {
+ return '标题过长';
+ }
+
+ $name = HTML::escape($name);
+
+ if ($name === '') {
+ return '无效编码';
+ }
+
+ $vdata['name'] = $name;
+
return '';
},
null
@@ -35,23 +51,25 @@
);
$time_form->addVInput(
'last_min', 'text', '时长(单位:分钟)', 180,
- function($str) {
- return !validateUInt($str) ? '必须为一个整数' : '';
+ function($str, &$vdata) {
+ if (!validateUInt($str)) {
+ return '必须为一个整数';
+ }
+
+ $vdata['last_min'] = $str;
+
+ return '';
},
null
);
$time_form->handle = function(&$vdata) {
$start_time_str = $vdata['start_time']->format('Y-m-d H:i:s');
-
- $purifier = HTML::purifier_inline();
+ $esc_name = DB::escape($vdata['name']);
+ $esc_last_min = DB::escape($vdata['last_min']);
- $esc_name = $_POST['name'];
- $esc_name = $purifier->purify($esc_name);
- $esc_name = DB::escape($esc_name);
-
- DB::query("insert into contests (name, start_time, last_min, status) values ('$esc_name', '$start_time_str', ${_POST['last_min']}, 'unfinished')");
+ DB::query("insert into contests (name, start_time, last_min, status) values ('$esc_name', '$start_time_str', $esc_last_min, 'unfinished')");
};
- $time_form->succ_href="/contests";
+ $time_form->succ_href = "/contests";
$time_form->runAtServer();
?>
diff --git a/web/app/controllers/contest_confirmation.php b/web/app/controllers/contest_confirmation.php
new file mode 100644
index 0000000..c72c39a
--- /dev/null
+++ b/web/app/controllers/contest_confirmation.php
@@ -0,0 +1,77 @@
+ CONTEST_IN_PROGRESS) {
+ redirectTo("/contest/{$contest['id']}");
+ }
+
+ $confirm_form = new UOJForm('confirm');
+ $confirm_form->submit_button_config['class_str'] = 'btn btn-primary';
+ $confirm_form->submit_button_config['margin_class'] = 'mt-3';
+ $confirm_form->submit_button_config['text'] = '我已核对信息,确认参加比赛';
+ $confirm_form->handle = function() use ($myUser, $contest) {
+ DB::update("update contests_registrants set has_participated = 1 where username = '{$myUser['username']}' and contest_id = {$contest['id']}");
+ };
+ $confirm_form->succ_href = "/contest/{$contest['id']}";
+ $confirm_form->runAtServer();
+ ?>
+
+
+
+ 您即将参加比赛 “= $contest['name'] ?>”,请在正式参赛前仔细核对以下比赛信息:确认参赛
+
+
+
+
+
+
+
+
+
+
+
+
+ 比赛名称
+ = $contest['name'] ?>
+
+
+ 参赛选手
+ = getUserLink($myUser['username']) ?>
+
+
+ 开始时间
+ = $contest['start_time_str'] ?>
+
+
+ 结束时间
+ = $contest['end_time_str'] ?>
+
+
+
+ 比赛赛制
+ = $contest['extra_config']['contest_type'] ?: 'OI' ?>
+ 比赛正在进行中
很遗憾,您尚未报名。比赛结束后再来看吧~
"); + if (Auth::check()) { + if (!hasParticipated($myUser, $contest)) { + redirectTo("/contest/{$contest['id']}/confirm"); + } + } else { + redirectToLogin(); } } else { - if (!isNormalUser($myUser)) { + if (!hasRegistered($myUser, $contest) && !isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) { become403Page(); } } + } else { + if ($contest['cur_progress'] == CONTEST_IN_PROGRESS) { + if (hasRegistered($myUser, $contest)) { + if (!hasParticipated($myUser, $contest)) { + redirectTo("/contest/{$contest['id']}/confirm"); + } + } + } } - + if (isset($_GET['tab'])) { $cur_tab = $_GET['tab']; } else { diff --git a/web/app/controllers/contest_manage.php b/web/app/controllers/contest_manage.php index 3a0c36f..d9e60a8 100644 --- a/web/app/controllers/contest_manage.php +++ b/web/app/controllers/contest_manage.php @@ -2,7 +2,8 @@ if (!Auth::check()) { redirectToLogin(); } - + + requireLib('bootstrap5'); requirePHPLib('form'); if (!validateUInt($_GET['id']) || !($contest = queryContest($_GET['id']))) { @@ -10,298 +11,672 @@ } genMoreContestInfo($contest); - if (!isSuperUser($myUser)) { + if (!hasContestPermission($myUser, $contest)) { become403Page(); } - - $time_form = new UOJForm('time'); - $time_form->addInput( - 'name', 'text', '比赛标题', $contest['name'], - function($str) { - return ''; - }, - null - ); - $time_form->addInput( - 'start_time', 'text', '开始时间', $contest['start_time_str'], - function($str, &$vdata) { - try { - $vdata['start_time'] = new DateTime($str); - } catch (Exception $e) { - return '无效时间格式'; - } - return ''; - }, - null - ); - $time_form->addInput( - 'last_min', 'text', '时长(单位:分钟)', $contest['last_min'], - function($str) { - return !validateUInt($str) ? '必须为一个整数' : ''; - }, - null - ); - $time_form->handle = function(&$vdata) { - global $contest; - $start_time_str = $vdata['start_time']->format('Y-m-d H:i:s'); - - $purifier = HTML::purifier_inline(); - - $esc_name = $_POST['name']; - $esc_name = $purifier->purify($esc_name); - $esc_name = DB::escape($esc_name); - - DB::update("update contests set start_time = '$start_time_str', last_min = {$_POST['last_min']}, name = '$esc_name' where id = {$contest['id']}"); - }; - - $managers_form = newAddDelCmdForm('managers', - function($username) { - if (!validateUsername($username) || !queryUser($username)) { - return "不存在名为{$username}的用户"; - } - return ''; - }, - function($type, $username) { - global $contest; - if ($type == '+') { - DB::query("insert into contests_permissions (contest_id, username) values (${contest['id']}, '$username')"); - } elseif ($type == '-') { - DB::query("delete from contests_permissions where contest_id = ${contest['id']} and username = '$username'"); - } - } - ); + if (isset($_GET['tab'])) { + $cur_tab = $_GET['tab']; + } else { + $cur_tab = 'profile'; + } + + $tabs_info = [ + 'profile' => [ + 'name' => '基本信息', + 'url' => "/contest/{$contest['id']}/manage/profile", + ], + 'problems' => [ + 'name' => '试题', + 'url' => "/contest/{$contest['id']}/manage/problems", + ], + 'managers' => [ + 'name' => '管理者', + 'url' => "/contest/{$contest['id']}/manage/managers", + ], + 'others' => [ + 'name' => '其他', + 'url' => "/contest/{$contest['id']}/manage/others", + ], + ]; - $problems_form = newAddDelCmdForm('problems', - function($cmd) { - if (!preg_match('/^(\d+)\s*(\[\S+\])?$/', $cmd, $matches)) { - return "无效题号"; - } - $problem_id = $matches[1]; - if (!validateUInt($problem_id) || !($problem = queryProblemBrief($problem_id))) { - return "不存在题号为{$problem_id}的题"; - } - if (!hasProblemPermission(Auth::user(), $problem)) { - return "无权添加题号为{$problem_id}的题"; - } - return ''; - }, - function($type, $cmd) { - global $contest; - - if (!preg_match('/^(\d+)\s*(\[\S+\])?$/', $cmd, $matches)) { - return "无效题号"; - } - - $problem_id = $matches[1]; - - if ($type == '+') { - $dfn = DB::selectFirst("select max(dfn) from contests_problems where contest_id = {$contest['id']}")['max(dfn)'] + 1; - DB::insert("insert into contests_problems (contest_id, problem_id, dfn) values ({$contest['id']}, '$problem_id', $dfn)"); - } elseif ($type == '-') { - DB::delete("delete from contests_problems where contest_id = {$contest['id']} and problem_id = '$problem_id'"); - } - - if (isset($matches[2])) { - switch ($matches[2]) { - case '[sample]': - unset($contest['extra_config']["problem_$problem_id"]); - break; - case '[full]': - $contest['extra_config']["problem_$problem_id"] = 'full'; - break; - case '[no-details]': - $contest['extra_config']["problem_$problem_id"] = 'no-details'; - break; + if (!isset($tabs_info[$cur_tab])) { + become404Page(); + } + + if ($cur_tab == 'profile') { + $profile_form = new UOJForm('time'); + $profile_form->addVInput( + 'name', 'text', '比赛标题', $contest['name'], + function($name, &$vdata) { + if ($name == '') { + return '标题不能为空'; + } + + if (strlen($name) > 100) { + return '标题过长'; } - $esc_extra_config = json_encode($contest['extra_config']); - $esc_extra_config = DB::escape($esc_extra_config); - DB::update("update contests set extra_config = '$esc_extra_config' where id = {$contest['id']}"); - } - } - ); - if (isSuperUser($myUser)) { - $version_form = new UOJForm('version'); - $version_form->addInput('standings_version', 'text', '排名版本', $contest['extra_config']['standings_version'], - function ($x) { - if (!validateUInt($x) || $x < 1 || $x > 2) { - return '不是合法的版本号'; + $name = HTML::escape($name); + + if ($name === '') { + return '无效编码'; + } + + $vdata['name'] = $name; + + return ''; + }, + null + ); + $profile_form->addVInput( + 'start_time', 'text', '开始时间', $contest['start_time_str'], + function($str, &$vdata) { + try { + $vdata['start_time'] = new DateTime($str); + } catch (Exception $e) { + return '无效时间格式'; } return ''; }, null ); - $version_form->handle = function() { - global $contest; + $profile_form->addVInput( + 'last_min', 'text', '时长(单位:分钟)', $contest['last_min'], + function($str, &$vdata) { + if (!validateUInt($str)) { + return '必须为一个整数'; + } + + $vdata['last_min'] = $str; + + return ''; + }, + null + ); + $profile_form->handle = function(&$vdata) use ($contest) { + $start_time_str = $vdata['start_time']->format('Y-m-d H:i:s'); + $esc_name = DB::escape($vdata['name']); + $esc_last_min = DB::escape($vdata['last_min']); + + DB::update("update contests set start_time = '$start_time_str', last_min = {$_POST['last_min']}, name = '$esc_name' where id = {$contest['id']}"); + + dieWithJsonData(['status' => 'success', 'message' => '修改成功']); + }; + $profile_form->setAjaxSubmit(<<# | -用户名 | -', $row_id, ' | ', '', getUserLink($row['username']), ' | ', ''; + dieWithJsonData(['status' => 'success', 'message' => '修改成功']); + }; + $blog_link_contests->setAjaxSubmit(<<
---|
命令格式:命令一行一个,+mike表示把mike加入管理者,-mike表示把mike从管理者中移除
- printHTML(); ?> -# | -试题名 | -', $problem['id'], ' | ', '', getProblemLink($problem), ' ', "[$problem_config_str]", ' | ', ''; + + $(window).scrollTop(0); +} +EOD); + $blog_link_contests->runAtServer(); } + ?> - -
---|
命令格式:命令一行一个,+233表示把题号为233的试题加入比赛,-233表示把题号为233的试题从比赛中移除
- printHTML(); ?> + +您即将报名比赛 “= $contest['name'] ?>”,请在报名前仔细阅读以下比赛规则:
+ +很遗憾,您尚未报名。比赛结束后再来看吧~
"); + if (Auth::check()) { + if (hasParticipated($myUser, $contest)) { + $is_in_contest = true; + } else { + redirectTo("/contest/{$contest['id']}/confirm"); + } } else { - $is_in_contest = true; - DB::update("update contests_registrants set has_participated = 1 where username = '{$myUser['username']}' and contest_id = {$contest['id']}"); + redirectToLogin(); } } else { $ban_in_contest = !isProblemVisibleToUser($problem, $myUser); + + if (!hasRegistered($myUser, $contest) && !isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) { + become403Page(); + } } } else { if ($contest['cur_progress'] == CONTEST_IN_PROGRESS) { - $is_in_contest = true; - DB::update("update contests_registrants set has_participated = 1 where username = '{$myUser['username']}' and contest_id = {$contest['id']}"); + if (hasRegistered($myUser, $contest)) { + if (hasParticipated($myUser, $contest)) { + $is_in_contest = true; + } else { + redirectTo("/contest/{$contest['id']}/confirm"); + } + } } } } else { diff --git a/web/app/libs/uoj-contest-lib.php b/web/app/libs/uoj-contest-lib.php index d2115b6..c884522 100644 --- a/web/app/libs/uoj-contest-lib.php +++ b/web/app/libs/uoj-contest-lib.php @@ -10,6 +10,7 @@ function genMoreContestInfo(&$contest) { $contest['start_time'] = new DateTime($contest['start_time']); $contest['end_time'] = clone $contest['start_time']; $contest['end_time']->add(new DateInterval("PT${contest['last_min']}M")); + $contest['end_time_str'] = $contest['end_time']->format('Y-m-d H:i:s'); if ($contest['status'] == 'unfinished') { if (UOJTime::$time_now < $contest['start_time']) { diff --git a/web/app/route.php b/web/app/route.php index b140d0c..59216bf 100644 --- a/web/app/route.php +++ b/web/app/route.php @@ -31,7 +31,8 @@ Route::group([ Route::any('/contest/{id}', '/contest_inside.php'); Route::any('/contest/{id}/registrants', '/contest_members.php'); Route::any('/contest/{id}/register', '/contest_registration.php'); - Route::any('/contest/{id}/manage', '/contest_manage.php'); + Route::any('/contest/{id}/confirm', '/contest_confirmation.php'); + Route::any('/contest/{id}/manage(?:/{tab})?', '/contest_manage.php'); Route::any('/contest/{id}/submissions', '/contest_inside.php?tab=submissions'); Route::any('/contest/{id}/standings', '/contest_inside.php?tab=standings'); Route::any('/contest/{id}/after_contest_standings', '/contest_inside.php?tab=after_contest_standings'); diff --git a/web/js/uoj.js b/web/js/uoj.js index 86d2860..087f661 100644 --- a/web/js/uoj.js +++ b/web/js/uoj.js @@ -1144,7 +1144,7 @@ function showStandings(config) { var col_tr = '