diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index 0de2efe..02ce760 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -745,6 +745,29 @@ CREATE TABLE `lists` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `lists_contents` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `lists_contents` ( + `id` int NOT NULL, + `content` longtext COLLATE utf8mb4_unicode_ci NOT NULL, + `content_md` longtext COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `lists_contents` +-- + +LOCK TABLES `lists_contents` WRITE; +/*!40000 ALTER TABLE `lists_contents` DISABLE KEYS */; +/*!40000 ALTER TABLE `lists_contents` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `lists_problems` -- @@ -759,6 +782,15 @@ CREATE TABLE `lists_problems` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Dumping data for table `lists_problems` +-- + +LOCK TABLES `lists_problems` WRITE; +/*!40000 ALTER TABLE `lists_problems` DISABLE KEYS */; +/*!40000 ALTER TABLE `lists_problems` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `lists_tags` -- @@ -775,6 +807,15 @@ CREATE TABLE `lists_tags` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Dumping data for table `lists_tags` +-- + +LOCK TABLES `lists_tags` WRITE; +/*!40000 ALTER TABLE `lists_tags` DISABLE KEYS */; +/*!40000 ALTER TABLE `lists_tags` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `search_requests` -- diff --git a/web/app/controllers/group_assignment.php b/web/app/controllers/group_assignment.php index 3e20348..ab6a622 100644 --- a/web/app/controllers/group_assignment.php +++ b/web/app/controllers/group_assignment.php @@ -1,189 +1,171 @@ +if (($group['is_hidden'] || $list['is_hidden']) && !isSuperUser($myUser)) { + become403Page(); +} +?>
- -
+ +
+

+ 作业: +

+
    +
  • 对应题单:#
  • +
  • 所属小组:
  • +
  • 结束时间:
  • +
-

- 作业: -

-
    -
  • 对应题单:#
  • -
  • 所属小组:
  • -
  • 结束时间:
  • -
+ getProblemIDs(); + $users = queryGroupUsers($group['id']); + $usernames = []; + $n_users = count($users); + $submission_end_time = min(new DateTime(), DateTime::createFromFormat('Y-m-d H:i:s', $assignment['end_time'])); - [total_score, user => [username, realname], scores[]] - $standings = []; - - foreach ($usernames as $username) { - $user = queryUser($username); - $row = ['total_score' => 0]; - $scores = []; - - $row['user'] = [ - 'username' => $user['username'], - 'realname' => $user['realname'], - ]; - - $cond = "submitter = '{$user['username']}' AND unix_timestamp(submit_time) <= " . $submission_end_time->getTimestamp(); - - foreach ($problem_ids as $problem_id) { - $submission = DB::selectFirst("SELECT id, score FROM submissions WHERE problem_id = $problem_id AND $cond ORDER BY score DESC, id DESC"); - - if ($submission) { - $row['scores'][] = [ - 'submission_id' => $submission['id'], - 'score' => intval($submission['score']), - ]; - $row['total_score'] += $submission['score']; - } else { - $row['scores'][] = null; - } + foreach ($users as $user) { + $usernames[] = $user['username']; } - $standings[] = $row; - } - - usort($standings, function($lhs, $rhs) { - if ($lhs['total_score'] != $rhs['total_score']) { - return $rhs['total_score'] - $lhs['total_score']; - } + // standings: rank => [total_score, user => [username, realname], scores[]] + $standings = []; - return strcmp($lhs['user']['username'], $rhs['user']['username']); - }); - ?> + foreach ($usernames as $username) { + $user = UOJUser::query($username); + $row = ['total_score' => 0]; + $scores = []; -
+ $row['user'] = [ + 'username' => $user['username'], + 'realname' => $user['realname'], + ]; - + + +
+ + + + +
diff --git a/web/app/controllers/group_manage.php b/web/app/controllers/group_manage.php index deca22d..e41c0d6 100644 --- a/web/app/controllers/group_manage.php +++ b/web/app/controllers/group_manage.php @@ -1,94 +1,103 @@ [ - 'name' => '基本信息', - 'url' => "/group/{$group['id']}/manage/profile", - ], - 'assignments' => [ - 'name' => '作业管理', - 'url' => "/group/{$group['id']}/manage/assignments", - ], - 'users' => [ - 'name' => '用户管理', - 'url' => "/group/{$group['id']}/manage/users", - ] - ]; - - if (!isset($tabs_info[$cur_tab])) { - become404Page(); - } +if (!isSuperUser($myUser)) { + become403Page(); +} - if ($cur_tab == 'profile') { - $update_profile_form = new UOJBs4Form('update_profile'); - $update_profile_form->addVInput('name', 'text', '名称', $group['title'], - function($title, &$vdata) { - if ($title == '') { - return '名称不能为空'; - } - - if (strlen($title) > 100) { - return '名称过长'; - } +if (isset($_GET['tab'])) { + $cur_tab = $_GET['tab']; +} else { + $cur_tab = 'profile'; +} - $title = HTML::escape($title); - if ($title === '') { - return '无效编码'; - } +$tabs_info = [ + 'profile' => [ + 'name' => '基本信息', + 'url' => "/group/{$group['id']}/manage/profile", + ], + 'assignments' => [ + 'name' => '作业管理', + 'url' => "/group/{$group['id']}/manage/assignments", + ], + 'users' => [ + 'name' => '用户管理', + 'url' => "/group/{$group['id']}/manage/users", + ] +]; - $vdata['title'] = $title; +if (!isset($tabs_info[$cur_tab])) { + become404Page(); +} - return ''; - }, - null - ); - $update_profile_form->addVCheckboxes('is_hidden', [ - '0' => '公开', - '1' => '隐藏', - ], '可见性', $group['is_hidden']); - $update_profile_form->addVTextArea('announcement', '公告', $group['announcement'], - function($announcement, &$vdata) { - if (strlen($announcement) > 3000) { - return '公告过长'; - } +if ($cur_tab == 'profile') { + $update_profile_form = new UOJBs4Form('update_profile'); + $update_profile_form->addVInput( + 'name', + 'text', + '名称', + $group['title'], + function ($title, &$vdata) { + if ($title == '') { + return '名称不能为空'; + } - $vdata['announcement'] = $announcement; + if (strlen($title) > 100) { + return '名称过长'; + } - return ''; - }, null); - $update_profile_form->handle = function($vdata) use ($group) { - $esc_title = DB::escape($vdata['title']); - $is_hidden = $_POST['is_hidden']; - $esc_announcement = DB::escape($vdata['announcement']); + $title = HTML::escape($title); + if ($title === '') { + return '无效编码'; + } - DB::update("UPDATE `groups` SET title = '$esc_title', is_hidden = '$is_hidden', announcement = '$esc_announcement' WHERE id = {$group['id']}"); + $vdata['title'] = $title; - dieWithJsonData(['status' => 'success', 'message' => '修改成功']); - }; - $update_profile_form->setAjaxSubmit(<<addVCheckboxes('is_hidden', [ + '0' => '公开', + '1' => '隐藏', + ], '可见性', $group['is_hidden']); + $update_profile_form->addVTextArea( + 'announcement', + '公告', + $group['announcement'], + function ($announcement, &$vdata) { + if (strlen($announcement) > 3000) { + return '公告过长'; + } + + $vdata['announcement'] = $announcement; + + return ''; + }, + null + ); + $update_profile_form->handle = function ($vdata) use ($group) { + $esc_title = DB::escape($vdata['title']); + $is_hidden = $_POST['is_hidden']; + $esc_announcement = DB::escape($vdata['announcement']); + + DB::update("UPDATE `groups` SET title = '$esc_title', is_hidden = '$is_hidden', announcement = '$esc_announcement' WHERE id = {$group['id']}"); + + dieWithJsonData(['status' => 'success', 'message' => '修改成功']); + }; + $update_profile_form->setAjaxSubmit(<<submit_button_config['class_str'] = 'btn btn-secondary mt-3'; - $update_profile_form->submit_button_config['text'] = '更新'; - $update_profile_form->runAtServer(); - } elseif ($cur_tab == 'assignments') { - if (isset($_POST['submit-remove_assignment']) && $_POST['submit-remove_assignment'] == 'remove_assignment') { - $list_id = $_POST['list_id']; + $update_profile_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3'; + $update_profile_form->submit_button_config['text'] = '更新'; + $update_profile_form->runAtServer(); +} elseif ($cur_tab == 'assignments') { + if (isset($_POST['submit-remove_assignment']) && $_POST['submit-remove_assignment'] == 'remove_assignment') { + $list_id = $_POST['list_id']; - if (!validateUInt($list_id)) { - dieWithAlert('题单 ID 不合法。'); - } - - if (!queryAssignmentByGroupListID($group['id'], $list_id)) { - dieWithAlert('该题单不在作业中。'); - } - - DB::delete("DELETE FROM `groups_assignments` WHERE `list_id` = $list_id AND `group_id` = {$group['id']}"); - - dieWithAlert('移除成功!'); + if (!validateUInt($list_id)) { + dieWithAlert('题单 ID 不合法。'); } - $add_new_assignment_form = new UOJBs4Form('add_new_assignment'); - $add_new_assignment_form->addVInput('new_assignment_list_id', 'text', '题单 ID', '', - function ($list_id, &$vdata) use ($group) { - if (!validateUInt($list_id)) { - return '题单 ID 不合法'; - } + if (!queryAssignmentByGroupListID($group['id'], $list_id)) { + dieWithAlert('该题单不在作业中。'); + } - if (!($list = queryProblemList($list_id))) { - return '题单不存在'; - } + DB::delete("DELETE FROM `groups_assignments` WHERE `list_id` = $list_id AND `group_id` = {$group['id']}"); - if ($list['is_hidden'] != 0) { - return '题单是隐藏的'; - } + dieWithAlert('移除成功!'); + } - if (queryAssignmentByGroupListID($group['id'], $list_id)) { - return '该题单已经在作业中'; - } + $add_new_assignment_form = new UOJBs4Form('add_new_assignment'); + $add_new_assignment_form->addVInput( + 'new_assignment_list_id', + 'text', + '题单 ID', + '', + function ($list_id, &$vdata) use ($group) { + if (!validateUInt($list_id)) { + return '题单 ID 不合法'; + } - $vdata['list_id'] = $list_id; + $list = UOJList::query($list_id); - return ''; - }, - null - ); - $default_end_time = new DateTime(); - $default_end_time->setTime(22, 30, 0); - $default_end_time->add(new DateInterval("P7D")); - $add_new_assignment_form->addVInput('new_assignment_end_time', 'text', '截止时间', $default_end_time->format('Y-m-d H:i'), - function ($end_time, &$vdata) { - try { - $vdata['end_time'] = new DateTime($end_time); - } catch (Exception $e) { - return '无效时间格式'; - } + if (!$list) { + return '题单不存在'; + } - return ''; - }, - null - ); - $add_new_assignment_form->handle = function(&$vdata) use ($group) { - $esc_end_time = DB::escape($vdata['end_time']->format('Y-m-d H:i:s')); + if ($list->info['is_hidden']) { + return '题单是隐藏的'; + } - DB::insert("insert into groups_assignments (group_id, list_id, end_time) values ({$group['id']}, '{$vdata['list_id']}', '{$esc_end_time}')"); + if (queryAssignmentByGroupListID($group['id'], $list->info['id'])) { + return '该题单已经在作业中'; + } - dieWithJsonData([ - 'status' => 'success', - 'message' => '题单 #' . $vdata['list_id'] . ' 已经被添加到作业列表中,结束时间为 ' . $vdata['end_time']->format('Y-m-d H:i:s') . '。' - ]); - }; - $add_new_assignment_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3'; - $add_new_assignment_form->submit_button_config['text'] = '添加'; - $add_new_assignment_form->setAjaxSubmit(<<setTime(22, 30, 0); + $default_end_time->add(new DateInterval("P7D")); + $add_new_assignment_form->addVInput( + 'new_assignment_end_time', + 'text', + '截止时间', + $default_end_time->format('Y-m-d H:i'), + function ($end_time, &$vdata) { + try { + $vdata['end_time'] = new DateTime($end_time); + } catch (Exception $e) { + return '无效时间格式'; + } + + return ''; + }, + null + ); + $add_new_assignment_form->handle = function (&$vdata) use ($group) { + $esc_end_time = DB::escape($vdata['end_time']->format('Y-m-d H:i:s')); + + DB::insert("insert into groups_assignments (group_id, list_id, end_time) values ({$group['id']}, '{$vdata['list_id']}', '{$esc_end_time}')"); + + dieWithJsonData([ + 'status' => 'success', + 'message' => '题单 #' . $vdata['list_id'] . ' 已经被添加到作业列表中,结束时间为 ' . $vdata['end_time']->format('Y-m-d H:i:s') . '。' + ]); + }; + $add_new_assignment_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3'; + $add_new_assignment_form->submit_button_config['text'] = '添加'; + $add_new_assignment_form->setAjaxSubmit(<<runAtServer(); + $add_new_assignment_form->runAtServer(); - $hidden_time = new DateTime(); - $hidden_time->sub(new DateInterval('P7D')); - } elseif ($cur_tab == 'users') { - if (isset($_POST['submit-remove_user']) && $_POST['submit-remove_user'] == 'remove_user') { - $username = $_POST['remove_username']; + $hidden_time = new DateTime(); + $hidden_time->sub(new DateInterval('P7D')); +} elseif ($cur_tab == 'users') { + if (isset($_POST['submit-remove_user']) && $_POST['submit-remove_user'] == 'remove_user') { + $username = $_POST['remove_username']; + + if (!validateUsername($username)) { + dieWithAlert('用户名不合法。'); + } + + if (!queryUser($username)) { + dieWithAlert('用户不存在。'); + } + + if (!queryUserInGroup($group['id'], $username)) { + dieWithAlert('该用户不在小组中。'); + } + + DB::delete("DELETE FROM `groups_users` WHERE `username` = '$username' AND `group_id` = {$group['id']}"); + + dieWithAlert('移除成功!'); + } + + $add_new_user_form = new UOJBs4Form('add_new_user'); + $add_new_user_form->addVInput( + 'new_username', + 'text', + '用户名', + '', + function ($username, &$vdata) { + global $group_id; if (!validateUsername($username)) { - dieWithAlert('用户名不合法。'); + return '用户名不合法'; } if (!queryUser($username)) { - dieWithAlert('用户不存在。'); + return '用户不存在'; } - if (!queryUserInGroup($group['id'], $username)) { - dieWithAlert('该用户不在小组中。'); + if (queryUserInGroup($group_id, $username)) { + return '该用户已经在小组中'; } - DB::delete("DELETE FROM `groups_users` WHERE `username` = '$username' AND `group_id` = {$group['id']}"); + $vdata['username'] = $username; - dieWithAlert('移除成功!'); - } + return ''; + }, + null + ); + $add_new_user_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3'; + $add_new_user_form->submit_button_config['text'] = '添加'; + $add_new_user_form->handle = function (&$vdata) use ($group) { + DB::insert("insert into groups_users (group_id, username) values ({$group['id']}, '{$vdata['username']}')"); - $add_new_user_form = new UOJBs4Form('add_new_user'); - $add_new_user_form->addVInput('new_username', 'text', '用户名', '', - function ($username, &$vdata) { - global $group_id; - - if (!validateUsername($username)) { - return '用户名不合法'; - } - - if (!queryUser($username)) { - return '用户不存在'; - } - - if (queryUserInGroup($group_id, $username)) { - return '该用户已经在小组中'; - } - - $vdata['username'] = $username; - - return ''; - }, - null - ); - $add_new_user_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3'; - $add_new_user_form->submit_button_config['text'] = '添加'; - $add_new_user_form->handle = function(&$vdata) use ($group) { - DB::insert("insert into groups_users (group_id, username) values ({$group['id']}, '{$vdata['username']}')"); - - dieWithJsonData(['status' => 'success', 'message' => '已将用户名为 ' . $vdata['username'] . ' 的用户添加到本小组。']); - }; - $add_new_user_form->setAjaxSubmit(<< 'success', 'message' => '已将用户名为 ' . $vdata['username'] . ' 的用户添加到本小组。']); + }; + $add_new_user_form->setAjaxSubmit(<<runAtServer(); - } - ?> + $add_new_user_form->runAtServer(); +} +?>

@@ -284,63 +307,60 @@ EOD);

- -
+ + - - - -
- -
-
- -
-
- printHTML() ?> -
-
-
注意事项
-
    -
  • 隐藏的小组无法被普通用户查看,即使该用户属于本小组。
  • -
  • 公告支持 Markdown 语法,但不支持添加数学公式。
  • -
-
-
-
- -
-
- -
-
-
-
- + + +
+ +
+
+ +
+
+ printHTML() ?> +
+
+
注意事项
+
    +
  • 隐藏的小组无法被普通用户查看,即使该用户属于本小组。
  • +
  • 公告支持 Markdown 语法,但不支持添加数学公式。
  • +
+
+
+
+
+ +
+
+ +
+
+
+
+ 题单 ID 标题 @@ -349,132 +369,132 @@ EOD); 操作 EOD, - function($row) use ($group, $hidden_time) { - $list = queryProblemList($row['list_id']); - $end_time = DateTime::createFromFormat('Y-m-d H:i:s', $row['end_time']); + function ($row) use ($group, $hidden_time) { + $list = UOJList::query($row['list_id']); + $end_time = DateTime::createFromFormat('Y-m-d H:i:s', $row['end_time']); - echo ''; - echo '', $list['id'], ''; - echo ''; - echo '', HTML::escape($list['title']), ''; - if ($list['is_hidden']) { - echo ' ', UOJLocale::get('hidden'), ' '; - } - echo ''; - if ($end_time < $hidden_time) { - echo '已隐藏'; - } elseif ($end_time < UOJTime::$time_now) { - echo '已结束'; - } else { - echo '进行中'; - } - echo '', $end_time->format('Y-m-d H:i:s'), ''; - echo ''; - echo ' 编辑 '; - echo '
' - . '' - . '' - . '' - . '
'; - echo ''; - echo ''; - }, - [ - 'page_len' => 20, - 'div_classes' => ['table-responsive'], - 'table_classes' => ['table', 'align-middle'], - ] - ); - ?> -
-
- -
-
- printHTML() ?> -
-
-
注意事项
-
    -
  • 要被添加为作业的题单必须是公开的。
  • -
  • 请为学生预留合理的完成作业的时间。
  • -
  • 排行榜将在结束后停止更新。
  • -
  • 如需延长结束时间请删除后再次添加,排行数据不会丢失。
  • -
  • 作业结束七天后将会自动在小组主页中隐藏,但仍可直接通过 URL 访问。
  • -
+ echo ''; + echo '', $list->info['id'], ''; + echo ''; + echo '', $list->info['title'], ''; + if ($list->info['is_hidden']) { + echo ' ', UOJLocale::get('hidden'), ' '; + } + echo ''; + if ($end_time < $hidden_time) { + echo '已隐藏'; + } elseif ($end_time < UOJTime::$time_now) { + echo '已结束'; + } else { + echo '进行中'; + } + echo '', $end_time->format('Y-m-d H:i:s'), ''; + echo ''; + echo ' 编辑 '; + echo '
info['id'], ')吗?移除作业不会删除题单。")\'>' + . '' + . '' + . '' + . '
'; + echo ''; + echo ''; + }, + [ + 'page_len' => 20, + 'div_classes' => ['table-responsive'], + 'table_classes' => ['table', 'align-middle'], + ] + ); + ?> +
+
+ +
+
+ printHTML() ?> +
+
+
注意事项
+
    +
  • 要被添加为作业的题单必须是公开的。
  • +
  • 请为学生预留合理的完成作业的时间。
  • +
  • 排行榜将在结束后停止更新。
  • +
  • 如需延长结束时间请删除后再次添加,排行数据不会丢失。
  • +
  • 作业结束七天后将会自动在小组主页中隐藏,但仍可直接通过 URL 访问。
  • +
+
+
+
-
-
-
- -
-
- -
-
-
-
- +
+
+ +
+
+
+
+ 用户名 操作 EOD, - function($row) use ($group) { - echo ''; - echo '', getUserLink($row['username']), ''; - echo ''; - echo '
' - . '' - . '' - . '' - . '
'; - echo ''; - echo ''; - }, - [ - 'page_len' => 20, - 'div_classes' => ['table-responsive'], - 'table_classes' => ['table', 'align-middle'], - ] - ); - ?> -
-
- -
-
- printHTML() ?> -
-
-
注意事项
-
    -
  • 添加用户前请确认用户名是否正确以免带来不必要的麻烦。
  • -
  • 用户被添加到小组后将自动被加入组内的所有作业排行中。
  • -
+ function ($row) use ($group) { + echo ''; + echo '', getUserLink($row['username']), ''; + echo ''; + echo '
' + . '' + . '' + . '' + . '
'; + echo ''; + echo ''; + }, + [ + 'page_len' => 20, + 'div_classes' => ['table-responsive'], + 'table_classes' => ['table', 'align-middle'], + ] + ); + ?> +
+
+ +
+
+ printHTML() ?> +
+
+
注意事项
+
    +
  • 添加用户前请确认用户名是否正确以免带来不必要的麻烦。
  • +
  • 用户被添加到小组后将自动被加入组内的所有作业排行中。
  • +
+
+
+
-
+
- -
-
diff --git a/web/app/controllers/list.php b/web/app/controllers/list.php index c50685b..d6b7fa8 100644 --- a/web/app/controllers/list.php +++ b/web/app/controllers/list.php @@ -1,246 +1,229 @@ userCanView(Auth::user(), ['ensure' => true]); + +function getProblemTR($info) { + $problem = new UOJProblem($info); + + $html = HTML::tag_begin('tr', ['class' => 'text-center']); + $html .= HTML::tag('td', ['class' => $info['submission_id'] ? 'table-success' : ''], "#{$info['id']}"); + $html .= HTML::tag_begin('td', ['class' => 'text-start']); + $html .= $problem->getLink(['with' => 'none']); + if ($problem->isUserOwnProblem(Auth::user())) { + $html .= ' ' . UOJLocale::get('problems::my problem') . ' '; } - - requireLib('bootstrap5'); - requireLib('mathjax'); - requirePHPLib('form'); - requirePHPLib('judger'); - requirePHPLib('data'); - - $list_id = $_GET['id']; - - if (!validateUInt($list_id) || !($list = queryProblemList($list_id))) { - become404Page(); + if ($info['is_hidden']) { + $html .= ' ' . UOJLocale::get('hidden') . ' '; } - - if ($list['is_hidden'] && !isSuperUser($myUser)) { - become403Page(); - } - - function echoProblem($problem) { - global $myUser; - - if (isProblemVisibleToUser($problem, $myUser)) { - echo ''; - if ($problem['submission_id']) { - echo ''; - } else { - echo ''; - } - echo '#', $problem['id'], ''; - echo ''; - echo '', $problem['title'], ''; - - if ($problem['uploader'] == $myUser['username']) { - echo ' ', UOJLocale::get('problems::my problem') ,' '; - } - - if ($problem['is_hidden']) { - echo ' ', UOJLocale::get('hidden'), ' '; - } - - if (isset($_COOKIE['show_tags_mode'])) { - foreach (queryProblemTags($problem['id']) as $tag) { - echo ' '; - echo '', HTML::escape($tag), ''; - echo ' '; - } - } - echo ''; - if (isset($_COOKIE['show_submit_mode'])) { - $perc = $problem['submit_num'] > 0 ? round(100 * $problem['ac_num'] / $problem['submit_num']) : 0; - echo <<×{$problem['ac_num']} - ×{$problem['submit_num']} - -
-
{$perc}%
-
- -EOD; - } - if (isset($_COOKIE['show_difficulty'])) { - $extra_config = getProblemExtraConfig($problem); - if ($extra_config['difficulty'] == 0) { - echo ""; - } else { - echo "{$extra_config['difficulty']}"; - } - } - echo '', ClickZans::getBlock('P', $problem['id'], $problem['zan'], null, false), ''; - echo ''; + if (isset($_COOKIE['show_tags_mode'])) { + foreach ($problem->queryTags() as $tag) { + $html .= ' ' . '' . HTML::escape($tag) . '' . ' '; } } - - $header = ''; - $header .= 'ID'; - $header .= ''.UOJLocale::get('problems::problem').''; + $html .= HTML::tag_end('td'); if (isset($_COOKIE['show_submit_mode'])) { - $header .= ''.UOJLocale::get('problems::ac').''; - $header .= ''.UOJLocale::get('problems::submit').''; - $header .= ''.UOJLocale::get('problems::ac ratio').''; + $perc = $info['submit_num'] > 0 ? round(100 * $info['ac_num'] / $info['submit_num']) : 0; + $html .= '×' . $info['ac_num'] . ''; + $html .= '×' . $info['submit_num'] . ''; + $html .= ''; + $html .= '
'; + $html .= '
'; + $html .= $perc . '%'; + $html .= '
'; + $html .= '
'; + $html .= ''; } if (isset($_COOKIE['show_difficulty'])) { - $header .= ''.UOJLocale::get('problems::difficulty').''; + $html .= HTML::tag('td', [], $problem->getExtraConfig('difficulty')); } - $header .= ''.UOJLocale::get('appraisal').''; - $header .= ''; + $html .= HTML::tag('td', [], ClickZans::getCntBlock($problem->info['zan'])); + $html .= HTML::tag_end('tr'); + return $html; +} - $pag_config = [ - 'page_len' => 40, - 'col_names' => [ - 'best_ac_submissions.submission_id as submission_id', - 'problems.id as id', - 'problems.is_hidden as is_hidden', - 'problems.title as title', - 'problems.submit_num as submit_num', - 'problems.ac_num as ac_num', - 'problems.zan as zan', - 'problems.extra_config as extra_config', - 'problems.uploader as uploader', +$header = ''; +$header .= 'ID'; +$header .= '' . UOJLocale::get('problems::problem') . ''; +if (isset($_COOKIE['show_submit_mode'])) { + $header .= '' . UOJLocale::get('problems::ac') . ''; + $header .= '' . UOJLocale::get('problems::submit') . ''; + $header .= '' . UOJLocale::get('problems::ac ratio') . ''; +} +if (isset($_COOKIE['show_difficulty'])) { + $header .= '' . UOJLocale::get('problems::difficulty') . ''; +} +$header .= '' . UOJLocale::get('appraisal') . ''; +$header .= ''; + +$pag_config = [ + 'page_len' => 40, + 'col_names' => [ + 'best_ac_submissions.submission_id as submission_id', + 'problems.id as id', + 'problems.is_hidden as is_hidden', + 'problems.title as title', + 'problems.submit_num as submit_num', + 'problems.ac_num as ac_num', + 'problems.zan as zan', + 'problems.extra_config as extra_config', + 'problems.uploader as uploader', + ], + 'table_name' => [ + "problems", + "left join best_ac_submissions", + "on", [ + "best_ac_submissions.submitter" => Auth::id(), + "problems.id" => DB::raw("best_ac_submissions.problem_id") ], - 'table_name' => "problems left join best_ac_submissions on best_ac_submissions.submitter = '{$myUser['username']}' and problems.id = best_ac_submissions.problem_id inner join lists_problems lp on lp.list_id = {$list_id} and lp.problem_id = problems.id", - 'cond' => '1', - 'tail' => 'ORDER BY `id` ASC', - ]; - $pag = new Paginator($pag_config); - ?> + "inner join lists_problems", + "on", [ + "lists_problems.list_id" => UOJList::info('id'), + "lists_problems.problem_id" => DB::raw("problems.id"), + ], + ], + 'cond' => '1', + 'tail' => "order by id asc", + 'page_len' => 40, + 'post_filter' => function ($problem) { + return (new UOJProblem($problem))->userCanView(Auth::user()); + } +]; +$pag = new Paginator($pag_config); +?>
+ +
+ +
+

+ + (ID: #) + + + + + + +

- -
+ userCanManage(Auth::user())) : ?> +
+ + + +
+ +
+ - -
- -

- - (ID: #) - - - - - - -

- - -
- - - -
- - -
- - - -
-
-

题单简介

- purify(HTML::parsedown()->text($list['description'])) ?> - - - -

暂无简介

- -
-
- -
-
-
-
- - /> - + +
+
+

题单简介

+
+ queryContent()['content'] ?> +
+
-
- - /> - +
+
+
+
+ /> + +
+ +
+ /> + +
+ +
+ /> + +
+
-
- - /> - + + + pagination() ?> + +
+ get(), [ + 'table_attr' => [ + 'class' => ['table', 'uoj-table', 'mb-0'], + ], + 'tr' => function ($row, $idx) { + return getProblemTR($row); + } + ]); + ?>
+ + pagination() ?> +
-
+ - - -pagination() ?> - -
- - - - - -get() as $idx => $row): ?> - - -isEmpty()): ?> - - - - - -
- -
-
- -pagination() ?> - -
- - - +
diff --git a/web/app/controllers/list_edit.php b/web/app/controllers/list_edit.php deleted file mode 100644 index 7cb7802..0000000 --- a/web/app/controllers/list_edit.php +++ /dev/null @@ -1,542 +0,0 @@ - [ - 'name' => '基本信息', - 'url' => "/list/{$list['id']}/edit/profile", - ], - 'problems' => [ - 'name' => '题目管理', - 'url' => "/list/{$list['id']}/edit/problems", - ], - 'assignments' => [ - 'name' => '对应作业', - 'url' => "/list/{$list['id']}/edit/assignments", - ] - ]; - - if (!isset($tabs_info[$cur_tab])) { - become404Page(); - } - - if ($cur_tab == 'profile') { - $list_tags = queryProblemListTags($list_id); - - $update_profile_form = new UOJBs4Form('update_profile'); - $update_profile_form->addVInput('name', 'text', '标题', $list['title'], - function($title, &$vdata) { - if ($title == '') { - return '标题不能为空'; - } - - if (strlen($title) > 100) { - return '标题过长'; - } - - $title = HTML::escape($title); - if ($title === '') { - return '无效编码'; - } - - $vdata['title'] = $title; - - return ''; - }, - null - ); - $update_profile_form->addVCheckboxes('is_hidden', [ - '0' => '公开', - '1' => '隐藏', - ], '可见性', $list['is_hidden']); - $update_profile_form->addVInput('tags', 'text', '标签(多个标签用逗号隔开)', implode(', ', $list_tags), - function($tags_str, &$vdata) { - $tags_str = str_replace(',', ',', $tags_str); - $tags_raw = explode(',', $tags_str); - $tags = []; - - if (count($tags_raw) > 10) { - return '不能存在超过 10 个标签'; - } - - foreach ($tags_raw as $tag) { - $tag = HTML::escape(trim($tag)); - - if (strlen($tag) == 0) { - continue; - } - - if (strlen($tag) > 30) { - return '标签 “' . $tag .'” 太长'; - } - - if (in_array($tag, $tags, true)) { - return '标签 “' . $tag .'” 重复出现'; - } - - $tags[] = $tag; - } - - $vdata['tags'] = $tags; - - return ''; - }, - null); - $update_profile_form->addVTextArea('description', '描述', $list['description'], - function($description, &$vdata) { - if (strlen($description) > 3000) { - return '描述过长'; - } - - $vdata['description'] = $description; - - return ''; - }, null); - $update_profile_form->handle = function($vdata) use ($list, $list_tags) { - $esc_title = DB::escape($vdata['title']); - $is_hidden = $_POST['is_hidden']; - $esc_description = DB::escape($vdata['description']); - - DB::update("UPDATE `lists` SET `title` = '$esc_title', `is_hidden` = '$is_hidden', `description` = '$esc_description' WHERE id = {$list['id']}"); - - if ($vdata['tags'] !== $list_tags) { - DB::delete("DELETE FROM `lists_tags` WHERE `list_id` = {$list['id']}"); - - foreach ($vdata['tags'] as $tag) { - $esc_tag = DB::escape($tag); - - DB::insert("INSERT INTO `lists_tags` (list_id, tag) VALUES ({$list['id']}, '$esc_tag')"); - } - } - - dieWithJsonData(['status' => 'success', 'message' => '修改成功']); - }; - $update_profile_form->setAjaxSubmit(<<submit_button_config['class_str'] = 'btn btn-secondary mt-3'; - $update_profile_form->submit_button_config['text'] = '更新'; - $update_profile_form->runAtServer(); - } elseif ($cur_tab == 'problems') { - if (isset($_POST['submit-remove_problem']) && $_POST['submit-remove_problem'] == 'remove_problem') { - crsf_defend(); - - $problem_id = $_POST['problem_id']; - - if (!validateUInt($problem_id)) { - dieWithAlert('题目 ID 不合法'); - } - - if (!queryProblemBrief($problem_id)) { - dieWithAlert('题目不存在'); - } - - if (!queryProblemInList($list['id'], $problem_id)) { - dieWithAlert('题目不在题单中'); - } - - DB::delete("DELETE FROM lists_problems WHERE problem_id = {$problem_id} AND list_id = {$list['id']}"); - - dieWithAlert('移除成功!'); - } - - $n_problems = DB::selectCount("SELECT count(*) FROM `lists_problems` WHERE `list_id` = {$list['id']}"); - - $add_new_problem_form = new UOJBs4Form('add_new_problem'); - $add_new_problem_form->addVInput('problem_id', 'text', '题目 ID', '', - function ($problem_id, &$vdata) use ($list) { - if (!validateUInt($problem_id)) { - return 'ID 不合法'; - } - - if (!queryProblemBrief($problem_id)) { - return '题目不存在'; - } - - if (queryProblemInList($list['id'], $problem_id)) { - return '该题目已经在题单中'; - } - - $vdata['problem_id'] = $problem_id; - - return ''; - }, - null - ); - $add_new_problem_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3'; - $add_new_problem_form->submit_button_config['text'] = '添加'; - $add_new_problem_form->handle = function($vdata) use ($list) { - DB::insert("INSERT INTO `lists_problems` (`list_id`, `problem_id`) values ({$list['id']}, {$vdata['problem_id']})"); - - dieWithJsonData(['status' => 'success', 'message' => '已将题目 #' . $vdata['problem_id'] . ' 添加到题单 #' . $list['id'] .' 中']); - }; - $add_new_problem_form->setAjaxSubmit(<<runAtServer(); - } elseif ($cur_tab == 'assignments') { - if (isset($_POST['submit-remove_assignment']) && $_POST['submit-remove_assignment'] == 'remove_assignment') { - crsf_defend(); - - $group_id = $_POST['group_id']; - - if (!validateUInt($group_id)) { - dieWithAlert('小组 ID 不合法。'); - } - - if (!queryGroup($group_id)) { - dieWithAlert('小组不存在。'); - } - - if (!queryAssignmentByGroupListID($group_id, $list['id'])) { - dieWithAlert('该小组并未将本题单布置为作业。'); - } - - DB::delete("DELETE FROM groups_assignments WHERE group_id = {$group_id} AND list_id = {$list['id']}"); - - dieWithAlert('移除成功!'); - } - - $add_new_assignment_form = new UOJBs4Form('add_new_assignment'); - $add_new_assignment_form->addVInput('new_assignment_group_id', 'text', '小组 ID', '', - function ($group_id, &$vdata) use ($list) { - if (!validateUInt($group_id)) { - return '小组 ID 不合法'; - } - - if (!($list = queryGroup($group_id))) { - return '小组不存在'; - } - - if ($list['is_hidden'] != 0) { - return '题单是隐藏的'; - } - - if (queryAssignmentByGroupListID($group_id, $list['id'])) { - return '该题单已经是这个小组的作业'; - } - - $vdata['group_id'] = $group_id; - - return ''; - }, - null - ); - $default_end_time = new DateTime(); - $default_end_time->setTime(22, 30, 0); - $default_end_time->add(new DateInterval("P7D")); - $add_new_assignment_form->addVInput('new_assignment_end_time', 'text', '截止时间', $default_end_time->format('Y-m-d H:i'), - function ($end_time, &$vdata) { - try { - $vdata['end_time'] = new DateTime($end_time); - } catch (Exception $e) { - return '无效时间格式'; - } - - return ''; - }, - null - ); - $add_new_assignment_form->handle = function(&$vdata) use ($list) { - $esc_end_time = DB::escape($vdata['end_time']->format('Y-m-d H:i:s')); - - DB::insert("insert into groups_assignments (group_id, list_id, end_time) values ({$vdata['group_id']}, '{$list['id']}', '{$esc_end_time}')"); - - dieWithJsonData([ - 'status' => 'success', - 'message' => '题单 #' . $list['id'] . ' 已经被添加到小组 #' . $vdata['group_id'] . ' 的作业列表中,结束时间为 ' . $vdata['end_time']->format('Y-m-d H:i:s') . '。' - ]); - }; - $add_new_assignment_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3'; - $add_new_assignment_form->submit_button_config['text'] = '添加'; - $add_new_assignment_form->setAjaxSubmit(<<runAtServer(); - - $hidden_time = new DateTime(); - $hidden_time->sub(new DateInterval('P7D')); - } - ?> - - - -

- - (ID: #) - 管理 -

- -
- -
- - - -"> - 返回 - - -
- - - -
- -
-
- -
-
- printHTML() ?> -
-
-
注意事项
-
    -
  • 隐藏的题单无法被普通用户查看。
  • -
  • 题单描述支持 Markdown 语法。
  • -
-
-
-
-
- -
-
- -
-
-
- - ID - 标题 - 操作 - -EOD, - function ($row) { - echo ''; - - echo '', $row['id'], ''; - echo '', getProblemLink($row); - if ($row['is_hidden']) { - echo ' ', UOJLocale::get('hidden'), ' '; - } - echo ''; - echo ''; - echo '
'; - echo ''; - echo ''; - echo ''; - echo '
'; - echo ''; - - echo ''; - }, - [ - 'page_len' => 20, - 'div_classes' => ['table-responsive'], - 'table_classes' => ['table', 'align-middle'], - 'print_after_table' => function() use ($n_problems) { - echo '
共 ', $n_problems,' 道题目
'; - }, - ] - ); - ?> -
-
- -
-
- printHTML() ?> -
-
-
注意事项
-
    -
  • 隐藏的题目添加进题单后无法被普通用户查看。
  • -
  • 如当前题单已经被设置为某个小组的作业,则作业也会一并更新。
  • -
-
-
-
-
-
- -
-
- -
-
-
-
- - 小组 ID - 名称 - 状态 - 结束时间 - 操作 - -EOD, - function($row) use ($list, $hidden_time) { - $group = queryGroup($row['group_id']); - $end_time = DateTime::createFromFormat('Y-m-d H:i:s', $row['end_time']); - - echo ''; - echo '', $group['id'], ''; - echo '', '', HTML::escape($group['title']), '', ''; - if ($end_time < $hidden_time) { - echo '已隐藏'; - } elseif ($end_time < UOJTime::$time_now) { - echo '已结束'; - } else { - echo '进行中'; - } - echo '', $end_time->format('Y-m-d H:i:s'), ''; - echo ''; - echo ' 排行榜 '; - echo '
' - . '' - . '' - . '' - . '
'; - echo ''; - echo ''; - }, - [ - 'page_len' => 20, - 'div_classes' => ['table-responsive'], - 'table_classes' => ['table', 'align-middle'], - ] - ); - ?> -
-
- -
-
- printHTML() ?> -
-
-
注意事项
-
    -
  • 请为学生预留合理的完成作业的时间。
  • -
  • 排行榜将在作业结束后停止更新。
  • -
  • 如需延长结束时间请删除后再次添加,排行数据不会丢失。
  • -
  • 作业结束七天后将会自动在小组主页中隐藏,但仍可直接通过 URL 访问。
  • -
-
-
-
-
-
-
- -
- - -
- - diff --git a/web/app/controllers/list_manage.php b/web/app/controllers/list_manage.php new file mode 100644 index 0000000..88e400b --- /dev/null +++ b/web/app/controllers/list_manage.php @@ -0,0 +1,379 @@ +userCanManage(Auth::user()) || UOJResponse::page403(); + +$cur_tab = UOJRequest::get('tab', 'is_string', 'profile'); + +$tabs_info = [ + 'profile' => [ + 'name' => '基本信息', + 'url' => '/list/' . UOJList::info('id') . '/manage/profile', + ], + 'problems' => [ + 'name' => '题目管理', + 'url' => '/list/' . UOJList::info('id') . '/manage/problems', + ], +]; + +if (!isset($tabs_info[$cur_tab])) { + become404Page(); +} + +if ($cur_tab == 'profile') { + $update_profile_form = new UOJBs4Form('update_profile'); + $update_profile_form->addVInput( + 'name', + 'text', + '标题', + UOJList::info('title'), + function ($title, &$vdata) { + if ($title == '') { + return '标题不能为空'; + } + + if (strlen($title) > 100) { + return '标题过长'; + } + + $title = HTML::escape($title); + if ($title === '') { + return '无效编码'; + } + + $vdata['title'] = $title; + + return ''; + }, + null + ); + $update_profile_form->addVCheckboxes('is_hidden', [ + '0' => '公开', + '1' => '隐藏', + ], '可见性', UOJList::info('is_hidden')); + $update_profile_form->addVInput( + 'tags', + 'text', + '标签(多个标签用逗号隔开)', + implode(', ', UOJList::cur()->queryTags()), + function ($tags_str, &$vdata) { + $tags_raw = explode(',', str_replace(',', ',', $tags_str)); + $tags = []; + + if (count($tags_raw) > 10) { + return '不能存在超过 10 个标签'; + } + + foreach ($tags_raw as $tag) { + $tag = HTML::escape(trim($tag)); + + if (strlen($tag) == 0) { + continue; + } + + if (strlen($tag) > 30) { + return '标签 “' . $tag . '” 太长'; + } + + if (in_array($tag, $tags, true)) { + return '标签 “' . $tag . '” 重复出现'; + } + + $tags[] = $tag; + } + + $vdata['tags'] = $tags; + + return ''; + }, + null + ); + $update_profile_form->addVTextArea( + 'content_md', + '描述', + UOJList::cur()->queryContent()['content_md'], + function ($content_md, &$vdata) { + if (strlen($content_md) > 3000) { + return '描述过长'; + } + + $vdata['content_md'] = $content_md; + + return ''; + }, + null + ); + $update_profile_form->handle = function ($vdata) { + DB::update([ + "update lists", + "set", [ + "title" => $vdata['title'], + "is_hidden" => $_POST['is_hidden'], + ], + "where", [ + "id" => UOJList::info('id'), + ] + ]); + + DB::update([ + "update lists_contents", + "set", [ + "content" => HTML::purifier()->purify(HTML::parsedown()->text($vdata['content_md'])), + "content_md" => $vdata['content_md'], + ], + "where", [ + "id" => UOJList::info('id'), + ], + ]); + + UOJList::cur()->updateTags($vdata['tags']); + + dieWithJsonData(['status' => 'success', 'message' => '修改成功']); + }; + $update_profile_form->setAjaxSubmit(<<submit_button_config['class_str'] = 'btn btn-secondary mt-3'; + $update_profile_form->submit_button_config['text'] = '更新'; + $update_profile_form->runAtServer(); +} elseif ($cur_tab == 'problems') { + if (isset($_POST['submit-remove_problem']) && $_POST['submit-remove_problem'] == 'remove_problem') { + crsf_defend(); + + $problem = UOJProblem::query(UOJRequest::post('problem_id', 'validateUInt')); + + if (!$problem) { + dieWithAlert('题目不存在'); + } + + if (!UOJList::cur()->hasProblem($problem)) { + dieWithAlert('题目不在题单中'); + } + + DB::delete([ + "delete from lists_problems", + "where", [ + "problem_id" => $problem->info['id'], + "list_id" => UOJList::info('id'), + ], + ]); + + dieWithAlert('移除成功!'); + } + + $n_problems = DB::selectCount([ + "select count(*)", + "from lists_problems", + "where", [ + "list_id" => UOJList::info('id'), + ], + ]); + + $add_new_problem_form = new UOJBs4Form('add_new_problem'); + $add_new_problem_form->addVInput( + 'problem_id', + 'text', + '题目 ID', + '', + function ($problem_id, &$vdata) { + $problem = UOJProblem::query($problem_id); + + if (!$problem || !$problem->userCanView(Auth::user())) { + return '题目不存在'; + } + + if (UOJList::cur()->hasProblem($problem)) { + return '该题目已经在题单中'; + } + + $vdata['problem'] = $problem; + + return ''; + }, + null + ); + $add_new_problem_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3'; + $add_new_problem_form->submit_button_config['text'] = '添加'; + $add_new_problem_form->handle = function ($vdata) { + DB::insert([ + "insert into lists_problems", + DB::bracketed_fields(["list_id", "problem_id"]), + "values", DB::tuple([UOJList::info('id'), $vdata['problem']->info['id']]), + ]); + + dieWithJsonData(['status' => 'success', 'message' => '已将题目 #' . $vdata['problem']->info['id'] . ' 添加到题单 #' . UOJList::info('id') . ' 中']); + }; + $add_new_problem_form->setAjaxSubmit(<<runAtServer(); +} +?> + + + +

+ + (ID: #) + 管理 +

+ +
+ +
+ + + + 返回 + +
+ + + +
+ +
+
+ +
+
+ printHTML() ?> +
+
+
注意事项
+
    +
  • 隐藏的题单无法被普通用户查看。
  • +
  • 题单描述支持 Markdown 语法。
  • +
+
+
+
+
+ +
+
+ +
+
+
+ UOJList::info('id'), + "lists_problems.problem_id" => DB::raw("problems.id") + ] + ], + "1", + "order by id asc", + << + ID + 标题 + 操作 + + EOD, + function ($row) { + echo HTML::tag_begin('tr'); + + echo HTML::tag('td', ['class' => 'text-center'], $row['id']); + echo HTML::tag_begin('td'); + echo getProblemLink($row); + if ($row['is_hidden']) { + echo ' ', UOJLocale::get('hidden'), ' '; + } + echo HTML::tag_end('td'); + echo HTML::tag_begin('td'); + echo '
'; + echo ''; + echo ''; + echo ''; + echo '
'; + echo HTML::tag_end('td'); + + echo HTML::tag_end('tr'); + }, + [ + 'page_len' => 20, + 'div_classes' => ['table-responsive'], + 'table_classes' => ['table', 'align-middle'], + 'print_after_table' => function () use ($n_problems) { + echo '
共 ', $n_problems, ' 道题目
'; + }, + ] + ); + ?> +
+
+ +
+
+ printHTML() ?> +
+
+
注意事项
+
    +
  • 隐藏的题目添加进题单后无法被普通用户查看。
  • +
  • 如当前题单已经被设置为某个小组的作业,则作业也会一并更新。
  • +
+
+
+
+
+
+ +
+ +
+ + diff --git a/web/app/controllers/lists.php b/web/app/controllers/lists.php index 21396be..4c9691d 100644 --- a/web/app/controllers/lists.php +++ b/web/app/controllers/lists.php @@ -1,160 +1,155 @@ handle = function () { + DB::query("insert into lists (title, is_hidden) values ('未命名题单', 1)"); + }; + $new_list_form->submit_button_config['align'] = 'right'; + $new_list_form->submit_button_config['class_str'] = 'btn btn-primary'; + $new_list_form->submit_button_config['text'] = UOJLocale::get('problems::add new list'); + $new_list_form->submit_button_config['smart_confirm'] = ''; + + $new_list_form->runAtServer(); +} + +function getListTR($info) { + $list = new UOJList($info); + $problems = $list->getProblemIDs(); + $accepted = DB::selectCount([ + "select count(*)", + "from best_ac_submissions", + "where", [ + "submitter" => Auth::id(), + ["problem_id", "in", DB::tuple($problems)], + ], + ]); + + $html = HTML::tag_begin('tr', ['class' => 'text-center']); + $html .= HTML::tag('td', ['class' => $accepted == count($problems) ? 'table-success' : ''], "#{$list->info['id']}"); + $html .= HTML::tag_begin('td', ['class' => 'text-start']); + $html .= HTML::tag('a', ['href' => "/list/{$list->info['id']}"], $list->info['title']); + if ($list->info['is_hidden']) { + $html .= ' ' . UOJLocale::get('hidden') . ' '; } - - requireLib('bootstrap5'); - requirePHPLib('form'); - requirePHPLib('judger'); - requirePHPLib('data'); - - if (isSuperUser($myUser)) { - $new_list_form = new UOJBs4Form('new_list'); - $new_list_form->handle = function() { - DB::query("insert into lists (title, is_hidden) values ('未命名题单', 1)"); - }; - $new_list_form->submit_button_config['align'] = 'right'; - $new_list_form->submit_button_config['class_str'] = 'btn btn-primary'; - $new_list_form->submit_button_config['text'] = UOJLocale::get('problems::add new list'); - $new_list_form->submit_button_config['smart_confirm'] = ''; - - $new_list_form->runAtServer(); + foreach ($list->queryTags() as $tag) { + $html .= ' ' . $tag['tag'] . ' '; } - - function echoList($list) { - global $myUser; + $html .= HTML::tag('td', [], $accepted); + $html .= HTML::tag('td', [], count($problems)); + $html .= HTML::tag_end('td'); - if (isListVisibleToUser($list, $myUser)) { - echo ''; - if ($list['problem_count'] == $list['accepted'] && $list['problem_count'] > 0) { - echo ''; - } else { - echo ''; - } - echo '#', $list['list_id'], ''; + return $html; +} - echo ''; - echo '', $list['title'], ' '; +$cond = []; +$search_tag = UOJRequest::get('tag', 'is_string', null); +if (is_string($search_tag)) { + $cond[] = [ + DB::rawvalue($search_tag), "in", DB::rawbracket([ + "select tag from lists_tags", + "where", ["lists_tags.list_id" => DB::raw("lists.id")] + ]) + ]; +} - if ($list['is_hidden']) { - echo ' ', UOJLocale::get('hidden'), ' '; - } +if (empty($cond)) { + $cond = '1'; +} - foreach (queryProblemListTags($list['list_id']) as $tag) { - echo '', '', HTML::escape($tag), '', ' '; - } - echo ''; +$header = HTML::tag('tr', [], [ + HTML::tag('th', ['class' => 'text-center', 'style' => 'width:5em'], 'ID'), + HTML::tag('th', [], UOJLocale::get('problems::problem list')), + HTML::tag('th', ['class' => 'text-center', 'style' => 'width:5em'], UOJLocale::get('problems::ac')), + HTML::tag('th', ['class' => 'text-center', 'style' => 'width:5em'], UOJLocale::get('problems::total')), +]); - echo "{$list['accepted']}"; - echo "{$list['problem_count']}"; - - echo ''; - } +$pag = new Paginator([ + 'col_names' => ['*'], + 'table_name' => 'lists', + 'cond' => $cond, + 'tail' => "order by id desc", + 'page_len' => 40, + 'post_filter' => function ($info) { + return (new UOJList($info))->userCanView(Auth::user()); } - ?> +]); +?>
- -
+ +
- -
+ +
+

+ +

+ +
+ printHTML(); ?> +
+ +
+ -

- -

+
+
+ /> + +
+
- -
- printHTML(); ?> -
- - -
- - - - ID - {$list_caption} - {$ac_caption} - {$total_caption} - -EOD; - - $cond = []; - $search_tag = null; - - if (isset($_GET['tag'])) { - $search_tag = $_GET['tag']; - } - - if ($search_tag) { - $cond[] = "'" . DB::escape($search_tag) . "' in (select tag from lists_tags where lists_tags.list_id = a.id)"; - } - - if ($cond) { - $cond = join($cond, ' and '); - } else { - $cond = '1'; - } - - echoLongTable( - array('a.id as list_id', 'a.title as title', 'a.is_hidden as is_hidden', 'count(b.problem_id) as problem_count', 'count(c.submitter) as accepted'), - "lists a left join lists_problems b on a.id = b.list_id left join best_ac_submissions c on (b.problem_id = c.problem_id and c.submitter = '{$myUser['username']}')", - $cond, - 'group by a.id order by a.id desc', - $header, - function($list) use ($myUser) { - if (isListVisibleToUser($list, $myUser)) { - echo ''; - if ($list['problem_count'] == $list['accepted'] && $list['problem_count'] > 0) { - echo ''; + - + pagination() ?> +
+ get(), [ + 'table_attr' => [ + 'class' => ['table', 'uoj-table', 'mb-0'], + ], + 'tr' => function ($row, $idx) { + return getListTR($row); + } + ]); + ?> +
+ + pagination() ?> +
+ + + + +
diff --git a/web/app/controllers/problem_set.php b/web/app/controllers/problem_set.php index d0ad81d..7729fae 100644 --- a/web/app/controllers/problem_set.php +++ b/web/app/controllers/problem_set.php @@ -288,11 +288,11 @@ $pag = new Paginator([ $('#input-show_tags_mode').click(function() { if (this.checked) { $.cookie('show_tags_mode', '', { - path: '/problems' + path: '/' }); } else { $.removeCookie('show_tags_mode', { - path: '/problems' + path: '/' }); } location.reload(); @@ -300,11 +300,11 @@ $pag = new Paginator([ $('#input-show_submit_mode').click(function() { if (this.checked) { $.cookie('show_submit_mode', '', { - path: '/problems' + path: '/' }); } else { $.removeCookie('show_submit_mode', { - path: '/problems' + path: '/' }); } location.reload(); @@ -382,4 +382,4 @@ $pag = new Paginator([
- \ No newline at end of file + diff --git a/web/app/libs/uoj-query-lib.php b/web/app/libs/uoj-query-lib.php index 0d0760e..3741f47 100644 --- a/web/app/libs/uoj-query-lib.php +++ b/web/app/libs/uoj-query-lib.php @@ -37,33 +37,6 @@ function queryProblemBrief($id) { return DB::selectFirst("select * from problems where id = $id", MYSQLI_ASSOC); } -function queryProblemTags($id) { - $tags = array(); - $result = DB::query("select tag from problems_tags where problem_id = $id order by id"); - while ($row = DB::fetch($result, MYSQLI_NUM)) { - $tags[] = $row[0]; - } - return $tags; -} - -function queryProblemList($id) { - return DB::selectFirst("select * from lists where id = $id", MYSQLI_ASSOC); -} -function queryProblemListTags($id) { - $tags = array(); - $result = DB::query("select tag from lists_tags where list_id = $id order by id"); - if (!$result) { - return $tags; - } - while ($row = DB::fetch($result, MYSQLI_NUM)) { - $tags[] = $row[0]; - } - return $tags; -} -function queryProblemInList($list_id, $problem_id) { - return DB::selectFirst("SELECT * FROM lists_problems WHERE list_id = '$list_id' AND problem_id = '$problem_id'", MYSQLI_ASSOC); -} - function querySolution($problem_id, $blog_id) { return DB::selectFirst("select * from problems_solutions where blog_id='$blog_id' and problem_id='$problem_id'", MYSQLI_ASSOC); } diff --git a/web/app/models/HTML.php b/web/app/models/HTML.php index 1dc727e..63410df 100644 --- a/web/app/models/HTML.php +++ b/web/app/models/HTML.php @@ -60,7 +60,7 @@ class HTML { return ''; } public static function tag(string $name, array $attr, $content) { - return HTML::tag_begin($name, $attr) . $content . HTML::tag_end($name); + return HTML::tag_begin($name, $attr) . (is_array($content) ? implode('', $content) : $content) . HTML::tag_end($name); } public static function empty_tag(string $name, array $attr) { return '<' . $name . HTML::attr($attr) . ' />'; diff --git a/web/app/models/UOJList.php b/web/app/models/UOJList.php new file mode 100644 index 0000000..9255516 --- /dev/null +++ b/web/app/models/UOJList.php @@ -0,0 +1,61 @@ + $id] + ]); + if (!$info) { + return null; + } + return new UOJList($info); + } + + public function __construct($info) { + $this->info = $info; + } + + public function getProblemIDs() { + return array_map(fn ($x) => $x['problem_id'], DB::selectAll([ + DB::lc(), "select problem_id from lists_problems", + "where", ['list_id' => $this->info['id']], + "order by problem_id" + ])); + } + + public function hasProblem(UOJProblem $problem) { + return DB::selectFirst([ + DB::lc(), "select 1 from lists_problems", + "where", [ + 'list_id' => $this->info['id'], + 'problem_id' => $problem->info['id'] + ] + ]) != null; + } + + public function userCanManage(array $user = null) { + return isSuperUser($user); + } + + public function userCanView(array $user = null, array $cfg = []) { + $cfg += ['ensure' => false]; + if ($this->info['is_hidden'] && !$this->userCanManage($user)) { + $cfg['ensure'] && UOJResponse::page404(); + return false; + } + return true; + } +} + +UOJList::$table_for_content = 'lists_contents'; +UOJList::$key_for_content = 'id'; +UOJList::$fields_for_content = ['*']; +UOJList::$table_for_tags = 'lists_tags'; +UOJList::$key_for_tags = 'list_id'; diff --git a/web/app/models/UOJRequest.php b/web/app/models/UOJRequest.php index 709d58c..57ca237 100644 --- a/web/app/models/UOJRequest.php +++ b/web/app/models/UOJRequest.php @@ -4,7 +4,7 @@ class UOJRequest { const GET = 'get'; const POST = 'post'; - public static function get($name, $val=null, $default=null) { + public static function get($name, $val = null, $default = null) { if (!isset($_GET[$name])) { return $default; } @@ -14,7 +14,7 @@ class UOJRequest { return $_GET[$name]; } - public static function post($name, $val=null, $default=null) { + public static function post($name, $val = null, $default = null) { if (!isset($_POST[$name])) { return $default; } @@ -24,7 +24,7 @@ class UOJRequest { return $_POST[$name]; } - public static function data(string $method, string $name, callable $val=null, $default=null) { + public static function data(string $method, string $name, callable $val = null, $default = null) { if ($method == self::GET) { return self::get($name, $val, $default); } elseif ($method == self::POST) { diff --git a/web/app/route.php b/web/app/route.php index 53963ed..3422d02 100644 --- a/web/app/route.php +++ b/web/app/route.php @@ -28,7 +28,7 @@ Route::group( Route::any('/lists', '/lists.php'); Route::any('/list/{id}', '/list.php'); - Route::any('/list/{id}/edit(?:/{tab})?', '/list_edit.php'); + Route::any('/list/{id}/manage(?:/{tab})?', '/list_manage.php'); Route::any('/contests', '/contests.php'); Route::any('/contest/new', '/add_contest.php'); diff --git a/web/app/upgrade/16_list_v3/up.sql b/web/app/upgrade/16_list_v3/up.sql new file mode 100644 index 0000000..3451e43 --- /dev/null +++ b/web/app/upgrade/16_list_v3/up.sql @@ -0,0 +1,6 @@ +CREATE TABLE `lists_contents` ( + `id` int NOT NULL, + `content` longtext COLLATE utf8mb4_unicode_ci NOT NULL, + `content_md` longtext COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/web/app/upgrade/16_list_v3/upgrade.php b/web/app/upgrade/16_list_v3/upgrade.php new file mode 100644 index 0000000..3bc245d --- /dev/null +++ b/web/app/upgrade/16_list_v3/upgrade.php @@ -0,0 +1,28 @@ +purify($parsedown->text($info['description'])), + $info['description'], + ]), + ]); + } + + DB::query("alter table lists drop column description"); + } +};