diff --git a/db/Dockerfile b/db/Dockerfile index eb4c744..2ca033c 100644 --- a/db/Dockerfile +++ b/db/Dockerfile @@ -1,4 +1,4 @@ -FROM mysql:latest +FROM mysql:5.7 ADD . /opt/uoj_db WORKDIR /opt/uoj_db diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index 5e53a20..8d75f70 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -361,6 +361,33 @@ LOCK TABLES `custom_test_submissions` WRITE; /*!40000 ALTER TABLE `custom_test_submissions` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `groups` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `groups` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `title` text NOT NULL, + `is_hidden` tinyint(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `groups_users` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `groups_users` ( + `group_id` int(11) NOT NULL, + `username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`group_id`, `username`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `hacks` -- diff --git a/web/app/controllers/contest_members.php b/web/app/controllers/contest_members.php index eab9785..3daf9bd 100644 --- a/web/app/controllers/contest_members.php +++ b/web/app/controllers/contest_members.php @@ -10,6 +10,68 @@ } genMoreContestInfo($contest); + if (isSuperUser($myUser)) { + $add_new_contestant_form = new UOJForm('add_new_contestant_form'); + $add_new_contestant_form->addInput('new_username', 'text', '用户名', '', + function ($x) { + global $contest; + + if (!validateUsername($x)) return '用户名不合法'; + $user = queryUser($x); + if (!$user) return '用户不存在'; + + if (hasRegistered($user, $contest)) { + return '该用户已经报名'; + } + return ''; + }, + null + ); + $add_new_contestant_form->submit_button_config['align'] = 'compressed'; + $add_new_contestant_form->submit_button_config['text'] = '注册该用户'; + $add_new_contestant_form->handle = function() { + global $contest; + $username = $_POST['new_username']; + + $user = queryUser($username); + if (!$user) return; + + DB::query("replace into contests_registrants (username, user_rating, contest_id, has_participated) values ('{$user['username']}', {$user['rating']}, {$contest['id']}, 0)"); + + updateContestPlayerNum($contest); + }; + $add_new_contestant_form->runAtServer(); + + $add_group_to_contest_form = new UOJForm('add_group_to_contest'); + $add_group_to_contest_form->addInput('group_id', 'text', '小组 ID', '', + function ($x) { + global $contest; + + if (!validateUInt($x)) return '小组 ID 不合法'; + $group = queryGroup($x); + if (!$group) return '小组不存在'; + + return ''; + }, + null + ); + $add_group_to_contest_form->submit_button_config['align'] = 'compressed'; + $add_group_to_contest_form->submit_button_config['text'] = '注册该小组中的用户'; + $add_group_to_contest_form->handle = function() { + global $contest; + $group_id = $_POST['group_id']; + + $users = DB::selectAll("select b.username as username, b.rating as rating from groups_users a inner join user_info b on a.username = b.username where a.group_id = $group_id"); + + foreach ($users as $user) { + DB::query("replace into contests_registrants (username, user_rating, contest_id, has_participated) values ('{$user['username']}', {$user['rating']}, {$contest['id']}, 0)"); + } + + updateContestPlayerNum($contest); + }; + $add_group_to_contest_form->runAtServer(); + } + $has_contest_permission = hasContestPermission($myUser, $contest); $show_ip = $has_contest_permission; @@ -86,6 +148,14 @@ array('page_len' => 100, 'get_row_index' => '', 'print_after_table' => function() { + global $add_new_contestant_form, $add_group_to_contest_form; + + if (isset($add_new_contestant_form)) { + $add_new_contestant_form->printHTML(); + } + if (isset($add_group_to_contest_form)) { + $add_group_to_contest_form->printHTML(); + } } ) ); diff --git a/web/app/controllers/contest_registration.php b/web/app/controllers/contest_registration.php index 462e5c1..34b2098 100644 --- a/web/app/controllers/contest_registration.php +++ b/web/app/controllers/contest_registration.php @@ -15,7 +15,7 @@ $register_form = new UOJForm('register'); $register_form->handle = function() { global $myUser, $contest; - DB::query("insert into contests_registrants (username, contest_id, has_participated) values ('{$myUser['username']}', {$contest['id']}, 0)"); + DB::query("replace into contests_registrants (username, contest_id, has_participated) values ('{$myUser['username']}', {$contest['id']}, 0)"); updateContestPlayerNum($contest); }; $register_form->submit_button_config['class_str'] = 'btn btn-primary'; @@ -28,11 +28,11 @@

比赛规则

printHTML(); ?> diff --git a/web/app/controllers/group.php b/web/app/controllers/group.php new file mode 100644 index 0000000..48f5817 --- /dev/null +++ b/web/app/controllers/group.php @@ -0,0 +1,128 @@ +name = 'group'; + $group_editor->blog_url = null; + $group_editor->cur_data = array( + 'title' => $group['title'], + 'tags' => array(), + 'is_hidden' => $group['is_hidden'] + ); + $group_editor->label_text = array_merge($group_editor->label_text, array( + 'view blog' => '保存小组信息', + 'blog visibility' => '小组可见性' + )); + $group_editor->show_editor = false; + $group_editor->show_tags = false; + + $group_editor->save = function($data) { + global $group_id, $group; + DB::update("update `groups` set title = '".DB::escape($data['title'])."' where id = {$group_id}"); + + if ($data['is_hidden'] != $group['is_hidden'] ) { + DB::update("update `groups` set is_hidden = {$data['is_hidden']} where id = {$group_id}"); + } + }; + $group_editor->runAtServer(); + + $add_new_user_form = new UOJForm('add_new_user'); + $add_new_user_form->addInput('new_username', 'text', '用户名', '', + function ($x) { + global $group_id; + + if (!validateUsername($x)) return '用户名不合法'; + $user = queryUser($x); + if (!$user) return '用户不存在'; + + if (queryUserInGroup($group_id, $x)) { + return '该用户已经在小组中'; + } + + return ''; + }, + null + ); + $add_new_user_form->submit_button_config['align'] = 'compressed'; + $add_new_user_form->submit_button_config['text'] = '添加到小组'; + $add_new_user_form->handle = function() { + global $group_id, $myUser; + $username = $_POST['new_username']; + + DB::insert("insert into groups_users (group_id, username) values ({$group_id}, '{$username}')"); + }; + $add_new_user_form->runAtServer(); + + $delete_user_form = new UOJForm('delete_user'); + $delete_user_form->addInput('del_username', 'text', '用户名', '', + function ($x) { + global $group_id; + + if (!validateUsername($x)) return '用户名不合法'; + if (!queryUserInGroup($group_id, $x)) { + return '该用户不在小组中'; + } + + return ''; + }, + null + ); + $delete_user_form->submit_button_config['align'] = 'compressed'; + $delete_user_form->submit_button_config['text'] = '从小组中删除'; + $delete_user_form->handle = function() { + global $group_id, $myUser; + $username = $_POST['del_username']; + + DB::query("delete from groups_users where username='{$username}' and group_id={$group_id}"); + }; + $delete_user_form->runAtServer(); + } +?> + + + +

+

(小组 ID: )

+ +
+
+
+ +
+
+ + +
编辑小组信息
+
+ printHTML(); ?> +
+ +
添加用户到小组
+printHTML(); ?> + +
从小组中删除用户
+printHTML(); ?> + + + diff --git a/web/app/controllers/groups.php b/web/app/controllers/groups.php new file mode 100644 index 0000000..2ae493c --- /dev/null +++ b/web/app/controllers/groups.php @@ -0,0 +1,78 @@ +handle = function() { + DB::query("insert into `groups` (title, is_hidden) values ('新小组', 1)"); + }; + $new_group_form->submit_button_config['align'] = 'right'; + $new_group_form->submit_button_config['class_str'] = 'btn btn-primary'; + $new_group_form->submit_button_config['text'] = UOJLocale::get('add new group'); + $new_group_form->submit_button_config['smart_confirm'] = ''; + $new_group_form->runAtServer(); + } + + function echoGroup($group) { + global $myUser; + + echo ''; + echo ''; + echo '#', $group['group_id'], ''; + + echo ''; + if ($group['is_hidden']) { + echo ' [隐藏] '; + } + echo '', $group['title'], ''; + echo ''; + + echo "{$group['user_count']}"; + + echo ''; + } +?> + + + + + ID + {$groups_caption} + {$users_caption} + +EOD; + + if (isSuperUser($myUser)) { + $cond = "1"; + } else { + $cond = 'is_hidden = 0'; + } + + $from = "`groups` a left join groups_users b on a.id = b.group_id"; + + echoLongTable( + array('a.id as group_id', 'a.title as title', 'a.is_hidden as is_hidden', 'count(b.username) as user_count'), + $from, $cond, 'group by a.id order by a.id asc', + $header, + 'echoGroup', + array('page_len' => 100, + 'table_classes' => array('table', 'table-bordered', 'table-hover', 'table-striped'), + 'print_after_table' => function() { + global $myUser; + if (isSuperUser($myUser)) { + global $new_group_form; + $new_group_form->printHTML(); + } + }, + 'head_pagination' => true + ) + ); +?> + + diff --git a/web/app/libs/uoj-query-lib.php b/web/app/libs/uoj-query-lib.php index ddc8462..3364df8 100644 --- a/web/app/libs/uoj-query-lib.php +++ b/web/app/libs/uoj-query-lib.php @@ -82,6 +82,22 @@ function queryContestProblem($id) { return DB::selectFirst("select * from contest_problems where contest_id = $id", MYSQLI_ASSOC); } +function queryGroup($id) { + return DB::selectFirst("select * from groups where id = $id", MYSQLI_ASSOC); +} +function queryUserInGroup($group_id, $username) { + return DB::selectFirst("select * from groups_users where username='$username' and group_id='$group_id'", MYSQLI_ASSOC); +} +function queryGroupOfUser($username) { + return DB::selectAll("select b.title as title, b.id as id from groups_users a inner join groups b on a.group_id = b.id where a.username = '$username' and b.is_hidden = 0 order by id", MYSQLI_ASSOC); +} +function queryGroupmateCurrentAC($username) { + return DB::selectAll("select a.problem_id as problem_id, a.submitter as submitter, a.submission_id as submission_id, b.submit_time as submit_time, c.group_id as group_id, c.group_name as group_name, d.title as problem_title, b.submit_time as submit_time, e.realname as realname from best_ac_submissions a inner join submissions b on (a.submission_id = b.id) inner join (select a.username as username, any_value(a.group_id) as group_id, any_value(c.title) as group_name from groups_users a inner join (select a.group_id as group_id from groups_users a inner join groups b on a.group_id = b.id where a.username = '$username' and b.is_hidden = 0) b on a.group_id = b.group_id inner join groups c on a.group_id = c.id group by a.username) c on a.submitter = c.username inner join problems d on (a.problem_id = d.id and d.is_hidden = 0) inner join user_info e on a.submitter = e.username where b.submit_time > addtime(now(), '-360:00:00') order by b.submit_time desc limit 10", MYSQLI_ASSOC); +} +function queryGroupCurrentAC($group_id) { + return DB::selectAll("select a.problem_id as problem_id, a.submitter as submitter, a.submission_id as submission_id, b.submit_time as submit_time, d.title as problem_title, b.submit_time as submit_time, e.realname as realname from best_ac_submissions a inner join submissions b on (a.submission_id = b.id) inner join groups_users c on (a.submitter = c.username and c.group_id = $group_id) inner join problems d on (a.problem_id = d.id and d.is_hidden = 0) inner join user_info e on (a.submitter = e.username) where b.submit_time > addtime(now(), '-360:00:00') order by b.submit_time desc limit 10", MYSQLI_ASSOC); +} + function queryZanVal($id, $type, $user) { if ($user == null) { return 0; diff --git a/web/app/locale/basic/en.php b/web/app/locale/basic/en.php index 582a1d6..5da1d8b 100644 --- a/web/app/locale/basic/en.php +++ b/web/app/locale/basic/en.php @@ -11,6 +11,9 @@ return [ 'system manage' => 'System Manage', 'contests' => 'Contests', 'problems' => 'Problems', + 'groups' => 'Groups', + 'add new group' => 'Add new group', + 'users count' => 'Users', 'submissions' => 'Submissions', 'hacks' => 'Hack!', 'blogs' => 'Blogs', @@ -18,6 +21,7 @@ return [ 'all the announcements' => 'All the Announcements……', 'help' => 'Help', 'search' => 'Search', + 'news' => 'News', 'username' => 'Username', 'password' => 'Password', 'new password' => 'New password', diff --git a/web/app/locale/basic/zh-cn.php b/web/app/locale/basic/zh-cn.php index 7c8ce30..7b349fe 100644 --- a/web/app/locale/basic/zh-cn.php +++ b/web/app/locale/basic/zh-cn.php @@ -11,6 +11,9 @@ return [ 'system manage' => '系统管理', 'contests' => '比赛', 'problems' => '题库', + 'groups' => '小组', + 'add new group' => '添加新小组', + 'users count' => '用户数量', 'submissions' => '提交记录', 'hacks' => 'Hack!', 'blogs' => '博客', @@ -18,6 +21,7 @@ return [ 'all the announcements' => '所有公告……', 'help' => '帮助', 'search' => '搜索', + 'news' => '最新动态', 'username' => '用户名', 'password' => '密码', 'new password' => '新密码', diff --git a/web/app/route.php b/web/app/route.php index 06fdb99..a71638a 100644 --- a/web/app/route.php +++ b/web/app/route.php @@ -37,6 +37,9 @@ Route::group([ Route::any('/hacks', '/hack_list.php'); Route::any('/hack/{id}', '/hack.php'); + + Route::any('/groups', '/groups.php'); + Route::any('/group/{id}', '/group.php'); Route::any('/blogs', '/blogs.php'); if (UOJConfig::$data['switch']['blog-domain-mode'] != 3) { diff --git a/web/app/views/blog-editor.php b/web/app/views/blog-editor.php index 04f8b1b..44d889d 100644 --- a/web/app/views/blog-editor.php +++ b/web/app/views/blog-editor.php @@ -4,11 +4,15 @@
name}_title", 'text', $editor->label_text['title'], html_entity_decode($editor->cur_data['title'])) ?>
+ show_tags): ?>
name}_tags", 'text', $editor->label_text['tags'], join(', ', $editor->cur_data['tags'])) ?>
+ +show_editor): ?> name}_content_md", $editor->label_text['content'], $editor->cur_data['content_md']) ?> +
blog_url): ?> diff --git a/web/app/views/main-nav.php b/web/app/views/main-nav.php index 9edf904..06fde86 100644 --- a/web/app/views/main-nav.php +++ b/web/app/views/main-nav.php @@ -7,6 +7,7 @@