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 = '