super_manage.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. <?php
  2. requirePHPLib('form');
  3. requirePHPLib('judger');
  4. if ($myUser == null || !isSuperUser($myUser)) {
  5. become403Page();
  6. }
  7. $user_form = new UOJForm('user');
  8. $user_form->addInput('username', 'text', '用户名', '',
  9. function ($username) {
  10. if (!validateUsername($username)) {
  11. return '用户名不合法';
  12. }
  13. if (!queryUser($username)) {
  14. return '用户不存在';
  15. }
  16. return '';
  17. },
  18. null
  19. );
  20. $options = array(
  21. 'banneduser' => '设为封禁用户',
  22. 'normaluser' => '设为普通用户',
  23. 'superuser' => '设为超级用户'
  24. );
  25. $user_form->addSelect('op-type', $options, '操作类型', '');
  26. $user_form->handle = function() {
  27. global $user_form;
  28. $username = $_POST['username'];
  29. switch ($_POST['op-type']) {
  30. case 'banneduser':
  31. DB::update("update user_info set usergroup = 'B' where username = '{$username}'");
  32. break;
  33. case 'normaluser':
  34. DB::update("update user_info set usergroup = 'U' where username = '{$username}'");
  35. break;
  36. case 'superuser':
  37. DB::update("update user_info set usergroup = 'S' where username = '{$username}'");
  38. break;
  39. }
  40. };
  41. $user_form->runAtServer();
  42. $assign_certs_form = new UOJForm('assign_certs_form');
  43. $color_options = array('red' => '红色', 'blue' => '蓝色', 'green' => '绿色', 'purple' => '紫色', 'pink' => '粉色',
  44. 'olive' => '屎黄色', 'deepblue' => '深蓝',
  45. 'pro' => 'Pro', 'max' => 'Max', 'ultra' => 'Ultra');
  46. $assign_certs_form->addSelect('color-type', $color_options, '勋章颜色', '');
  47. $assign_certs_form->addInput('certs_user', 'text', '用户名', '',
  48. function ($username) {
  49. if (!validateUsername($username))
  50. return '用户名不合法';
  51. if (!queryUser($username))
  52. return '用户不存在';
  53. return '';
  54. }, null
  55. );
  56. $assign_certs_form->addInput('certs_name', 'text', '称号', '',
  57. function ($text) {
  58. if (strpos($text, '#') != false || strpos($text, ',') != false)
  59. return '不能含有井号或逗号';
  60. if (mb_strlen($text) > 8) return '称号过长' . $text;
  61. return '';
  62. }, null
  63. );
  64. $assign_certs_form->handle = function() {
  65. $username = $_POST['certs_user'];
  66. $text = $_POST['certs_name'];
  67. $color = $_POST['color-type'];
  68. $user = queryUser($username);
  69. $newcerts = $user['certslist'];
  70. if ($user['certslist'] != '') $newcerts = $newcerts . ',' . $color . '#' . $text;
  71. else $newcerts = $color . '#' . $text;
  72. DB::update("update user_info set certslist = '{$newcerts}' where username = '{$username}'");
  73. if ($user['certs'] == '') DB::update("update user_info set certs = '{$newcerts}' where username = '{$username}'");
  74. };
  75. $assign_certs_form->runAtServer();
  76. $user_attach_form = new UOJForm('user_attach_form');
  77. $user_attach_form->addInput('username', 'text', '用户名', '',
  78. function ($username) {
  79. if (!validateUsername($username)) {
  80. return '用户名不合法';
  81. }
  82. if (!queryUser($username)) {
  83. return '用户不存在';
  84. }
  85. return '';
  86. },
  87. null
  88. );
  89. $user_attach_form->addInput('group', 'text', '组名', '',
  90. function ($username) {
  91. if (!validateUsername($username))
  92. return '组名不合法';
  93. if (!queryUser($username))
  94. return '组不存在';
  95. if (substr($username, 0, 6) != 'group_')
  96. return '不是合法组(前缀非 group_)';
  97. return '';
  98. },
  99. null
  100. );
  101. $user_attach_form->handle = function() {
  102. $username = $_POST['username'];
  103. $group = $_POST['group'];
  104. attachUserToGroup (queryUser($username), queryUser($group));
  105. };
  106. $user_attach_form->runAtServer();
  107. $problem_attach_form = new UOJForm('problem_attach_form');
  108. $problem_attach_form->addInput('pid', 'text', '题号', '',
  109. function ($pid) {
  110. if (!validateUInt($pid)) {
  111. return '题号不合法';
  112. }
  113. if (!queryProblemBrief($pid)) {
  114. return '题目不存在';
  115. }
  116. return '';
  117. },
  118. null
  119. );
  120. $problem_attach_form->addInput('problem_group', 'text', '组名', '',
  121. function ($username) {
  122. if (!validateUsername($username))
  123. return '组名不合法';
  124. if (!queryUser($username))
  125. return '组不存在';
  126. if (substr($username, 0, 6) != 'group_')
  127. return '不是合法组(前缀非 group_)';
  128. return '';
  129. },
  130. null
  131. );
  132. $problem_attach_form->handle = function() {
  133. $pid = $_POST['pid'];
  134. $group = $_POST['problem_group'];
  135. attachProblemToGroup (queryProblemBrief ($pid), queryUser($group));
  136. };
  137. $problem_attach_form->runAtServer();
  138. $blog_link_contests = new UOJForm('blog_link_contests');
  139. $blog_link_contests->addInput('blog_id', 'text', '博客ID', '',
  140. function ($x) {
  141. if (!validateUInt($x)) {
  142. return 'ID不合法';
  143. }
  144. if (!queryBlog($x)) {
  145. return '博客不存在';
  146. }
  147. return '';
  148. },
  149. null
  150. );
  151. $blog_link_contests->addInput('contest_id', 'text', '比赛ID', '',
  152. function ($x) {
  153. if (!validateUInt($x)) {
  154. return 'ID不合法';
  155. }
  156. if (!queryContest($x)) {
  157. return '比赛不存在';
  158. }
  159. return '';
  160. },
  161. null
  162. );
  163. $blog_link_contests->addInput('title', 'text', '标题', '',
  164. function ($x) {
  165. return '';
  166. },
  167. null
  168. );
  169. $options = array(
  170. 'add' => '添加',
  171. 'del' => '删除'
  172. );
  173. $blog_link_contests->addSelect('op-type', $options, '操作类型', '');
  174. $blog_link_contests->handle = function() {
  175. $blog_id = $_POST['blog_id'];
  176. $contest_id = $_POST['contest_id'];
  177. $str = DB::selectFirst(("select * from contests where id='${contest_id}'"));
  178. $all_config = json_decode($str['extra_config'], true);
  179. $config = $all_config['links'];
  180. $n = count($config);
  181. if ($_POST['op-type'] == 'add') {
  182. $row = array();
  183. $row[0] = $_POST['title'];
  184. $row[1] = $blog_id;
  185. $config[$n] = $row;
  186. }
  187. if ($_POST['op-type'] == 'del') {
  188. for ($i = 0; $i < $n; $i++) {
  189. if ($config[$i][1] == $blog_id) {
  190. $config[$i] = $config[$n - 1];
  191. unset($config[$n - 1]);
  192. break;
  193. }
  194. }
  195. }
  196. $all_config['links'] = $config;
  197. $str = json_encode($all_config);
  198. $str = DB::escape($str);
  199. DB::query("update contests set extra_config='${str}' where id='${contest_id}'");
  200. };
  201. $blog_link_contests->runAtServer();
  202. $blog_link_index = new UOJForm('blog_link_index');
  203. $blog_link_index->addInput('blog_id2', 'text', '博客ID', '',
  204. function ($x) {
  205. if (!validateUInt($x)) {
  206. return 'ID不合法';
  207. }
  208. if (!queryBlog($x)) {
  209. return '博客不存在';
  210. }
  211. return '';
  212. },
  213. null
  214. );
  215. $blog_link_index->addInput('blog_level', 'text', '置顶级别(删除不用填)', '0',
  216. function ($x) {
  217. if (!validateUInt($x)) {
  218. return '数字不合法';
  219. }
  220. if ($x > 3) {
  221. return '该级别不存在';
  222. }
  223. return '';
  224. },
  225. null
  226. );
  227. $options = array(
  228. 'add' => '添加',
  229. 'del' => '删除'
  230. );
  231. $blog_link_index->addSelect('op-type2', $options, '操作类型', '');
  232. $blog_link_index->handle = function() {
  233. $blog_id = $_POST['blog_id2'];
  234. $blog_level = $_POST['blog_level'];
  235. if ($_POST['op-type2'] == 'add') {
  236. if (DB::selectFirst("select * from important_blogs where blog_id = {$blog_id}")) {
  237. DB::update("update important_blogs set level = {$blog_level} where blog_id = {$blog_id}");
  238. } else {
  239. DB::insert("insert into important_blogs (blog_id, level) values ({$blog_id}, {$blog_level})");
  240. }
  241. }
  242. if ($_POST['op-type2'] == 'del') {
  243. DB::delete("delete from important_blogs where blog_id = {$blog_id}");
  244. }
  245. };
  246. $blog_link_index->runAtServer();
  247. $blog_deleter = new UOJForm('blog_deleter');
  248. $blog_deleter->addInput('blog_del_id', 'text', '博客ID', '',
  249. function ($x) {
  250. if (!validateUInt($x)) {
  251. return 'ID不合法';
  252. }
  253. if (!queryBlog($x)) {
  254. return '博客不存在';
  255. }
  256. return '';
  257. },
  258. null
  259. );
  260. $blog_deleter->handle = function() {
  261. deleteBlog($_POST['blog_del_id']);
  262. };
  263. $blog_deleter->runAtServer();
  264. $contest_submissions_deleter = new UOJForm('contest_submissions');
  265. $contest_submissions_deleter->addInput('contest_id', 'text', '比赛ID', '',
  266. function ($x) {
  267. if (!validateUInt($x)) {
  268. return 'ID不合法';
  269. }
  270. if (!queryContest($x)) {
  271. return '博客不存在';
  272. }
  273. return '';
  274. },
  275. null
  276. );
  277. $contest_submissions_deleter->handle = function() {
  278. $contest = queryContest($_POST['contest_id']);
  279. genMoreContestInfo($contest);
  280. $contest_problems = DB::selectAll("select problem_id from contests_problems where contest_id = {$contest['id']}");
  281. foreach ($contest_problems as $problem) {
  282. $submissions = DB::selectAll("select * from submissions where problem_id = {$problem['problem_id']} and submit_time < '{$contest['start_time_str']}'");
  283. foreach ($submissions as $submission) {
  284. $content = json_decode($submission['content'], true);
  285. unlink(UOJContext::storagePath().$content['file_name']);
  286. DB::delete("delete from submissions where id = {$submission['id']}");
  287. updateBestACSubmissions($submission['submitter'], $submission['problem_id']);
  288. }
  289. }
  290. };
  291. $contest_submissions_deleter->runAtServer();
  292. $custom_test_deleter = new UOJForm('custom_test_deleter');
  293. $custom_test_deleter->addInput('last', 'text', '删除末尾记录', '5',
  294. function ($x, &$vdata) {
  295. if (!validateUInt($x)) {
  296. return '不合法';
  297. }
  298. $vdata['last'] = $x;
  299. return '';
  300. },
  301. null
  302. );
  303. $custom_test_deleter->handle = function(&$vdata) {
  304. $all = DB::selectAll("select * from custom_test_submissions order by id asc limit {$vdata['last']}");
  305. foreach ($all as $submission) {
  306. $content = json_decode($submission['content'], true);
  307. unlink(UOJContext::storagePath().$content['file_name']);
  308. }
  309. DB::delete("delete from custom_test_submissions order by id asc limit {$vdata['last']}");
  310. };
  311. $custom_test_deleter->runAtServer();
  312. $judger_adder = new UOJForm('judger_adder');
  313. $judger_adder->addInput('judger_adder_name', 'text', '评测机名称', '',
  314. function ($x, &$vdata) {
  315. if (!validateUsername($x)) {
  316. return '不合法';
  317. }
  318. if (DB::selectCount("select count(*) from judger_info where judger_name='$x'")!=0) {
  319. return '不合法';
  320. }
  321. $vdata['name'] = $x;
  322. return '';
  323. },
  324. null
  325. );
  326. $judger_adder->handle = function(&$vdata) {
  327. $password=uojRandString(32);
  328. DB::insert("insert into judger_info (judger_name,password) values('{$vdata['name']}','{$password}')");
  329. };
  330. $judger_adder->runAtServer();
  331. $judger_deleter = new UOJForm('judger_deleter');
  332. $judger_deleter->addInput('judger_deleter_name', 'text', '评测机名称', '',
  333. function ($x, &$vdata) {
  334. if (!validateUsername($x)) {
  335. return '不合法';
  336. }
  337. if (DB::selectCount("select count(*) from judger_info where judger_name='$x'")!=1) {
  338. return '不合法';
  339. }
  340. $vdata['name'] = $x;
  341. return '';
  342. },
  343. null
  344. );
  345. $judger_deleter->handle = function(&$vdata) {
  346. DB::delete("delete from judger_info where judger_name='{$vdata['name']}'");
  347. };
  348. $judger_deleter->runAtServer();
  349. $paste_deleter = new UOJForm('paste_deleter');
  350. $paste_deleter->addInput('paste_deleter_name', 'text', 'Paste ID', '',
  351. function ($x, &$vdata) {
  352. if (DB::selectCount("select count(*) from pastes where `index`='$x'")==0) {
  353. return '不合法';
  354. }
  355. $vdata['name'] = $x;
  356. return '';
  357. },
  358. null
  359. );
  360. $paste_deleter->handle = function(&$vdata) {
  361. DB::delete("delete from pastes where `index` = '${vdata['name']}'");
  362. };
  363. $paste_deleter->runAtServer();
  364. $judgerlist_cols = array('judger_name', 'password');
  365. $judgerlist_config = array();
  366. $judgerlist_header_row = <<<EOD
  367. <tr>
  368. <th>评测机名称</th>
  369. <th>密码</th>
  370. </tr>
  371. EOD;
  372. $judgerlist_print_row = function($row) {
  373. echo <<<EOD
  374. <tr>
  375. <td>{$row['judger_name']}</td>
  376. <td>{$row['password']}</td>
  377. </tr>
  378. EOD;
  379. };
  380. $banlist_cols = array('username', 'usergroup');
  381. $banlist_config = array();
  382. $banlist_header_row = <<<EOD
  383. <tr>
  384. <th>用户名</th>
  385. </tr>
  386. EOD;
  387. $banlist_print_row = function($row) {
  388. $hislink = getUserLink($row['username']);
  389. echo <<<EOD
  390. <tr>
  391. <td>${hislink}</td>
  392. </tr>
  393. EOD;
  394. };
  395. $cur_tab = isset($_GET['tab']) ? $_GET['tab'] : 'users';
  396. $tabs_info = array(
  397. 'users' => array(
  398. 'name' => '用户操作',
  399. 'url' => "/super-manage/users"
  400. ),
  401. 'blogs' => array(
  402. 'name' => '博客管理',
  403. 'url' => "/super-manage/blogs"
  404. ),
  405. 'submissions' => array(
  406. 'name' => '提交记录',
  407. 'url' => "/super-manage/submissions"
  408. ),
  409. 'custom-test' => array(
  410. 'name' => '自定义测试',
  411. 'url' => '/super-manage/custom-test'
  412. ),
  413. 'click-zan' => array(
  414. 'name' => '点赞管理',
  415. 'url' => '/super-manage/click-zan'
  416. ),
  417. 'search' => array(
  418. 'name' => '搜索管理',
  419. 'url' => '/super-manage/search'
  420. ),
  421. 'judger' => array(
  422. 'name' => '评测机管理',
  423. 'url' => '/super-manage/judger'
  424. ),
  425. 'paste' => array(
  426. 'name' => 'Paste管理',
  427. 'url' => '/super-manage/paste'
  428. ),
  429. 'groups' => array(
  430. 'name' => '用户组管理',
  431. 'url' => '/super-manage/groups'
  432. ),
  433. 'certs' => array(
  434. 'name' => '勋章管理',
  435. 'url' => '/super-manage/certs'
  436. )
  437. );
  438. if (!isset($tabs_info[$cur_tab])) {
  439. become404Page();
  440. }
  441. ?>
  442. <?php
  443. requireLib('hljs');
  444. requireLib('morris');
  445. ?>
  446. <?php echoUOJPageHeader('系统管理') ?>
  447. <div class="row">
  448. <div class="col-sm-3">
  449. <?= HTML::tablist($tabs_info, $cur_tab, 'nav-pills flex-column') ?>
  450. </div>
  451. <div class="col-sm-9">
  452. <?php if ($cur_tab === 'users'): ?>
  453. <?php $user_form->printHTML(); ?>
  454. <h3>封禁名单</h3>
  455. <?php echoLongTable($banlist_cols, 'user_info', "usergroup='B'", '', $banlist_header_row, $banlist_print_row, $banlist_config) ?>
  456. <?php elseif ($cur_tab === 'blogs'): ?>
  457. <div>
  458. <h4>添加到比赛链接</h4>
  459. <?php $blog_link_contests->printHTML(); ?>
  460. </div>
  461. <div>
  462. <h4>添加到公告</h4>
  463. <?php $blog_link_index->printHTML(); ?>
  464. </div>
  465. <div>
  466. <h4>删除博客</h4>
  467. <?php $blog_deleter->printHTML(); ?>
  468. </div>
  469. <?php elseif ($cur_tab === 'submissions'): ?>
  470. <div>
  471. <h4>删除赛前提交记录</h4>
  472. <?php $contest_submissions_deleter->printHTML(); ?>
  473. </div>
  474. <div>
  475. <h4>测评失败的提交记录</h4>
  476. <?php echoSubmissionsList("result_error = 'Judgement Failed'", 'order by id desc', array('result_hidden' => ''), $myUser); ?>
  477. </div>
  478. <?php elseif ($cur_tab === 'custom-test'): ?>
  479. <?php $custom_test_deleter->printHTML() ?>
  480. <?php
  481. $submissions_pag = new Paginator(array(
  482. 'col_names' => array('*'),
  483. 'table_name' => 'custom_test_submissions',
  484. 'cond' => '1',
  485. 'tail' => 'order by id asc',
  486. 'page_len' => 5
  487. ));
  488. foreach ($submissions_pag->get() as $submission) {
  489. $problem = queryProblemBrief($submission['problem_id']);
  490. $submission_result = json_decode($submission['result'], true);
  491. echo '<dl class="dl-horizontal">';
  492. echo '<dt>id</dt>';
  493. echo '<dd>', "#{$submission['id']}", '</dd>';
  494. echo '<dt>problem_id</dt>';
  495. echo '<dd>', "#{$submission['problem_id']}", '</dd>';
  496. echo '<dt>submit time</dt>';
  497. echo '<dd>', $submission['submit_time'], '</dd>';
  498. echo '<dt>submitter</dt>';
  499. echo '<dd>', $submission['submitter'], '</dd>';
  500. echo '<dt>judge_time</dt>';
  501. echo '<dd>', $submission['judge_time'], '</dd>';
  502. echo '</dl>';
  503. echoSubmissionContent($submission, getProblemCustomTestRequirement($problem));
  504. echoCustomTestSubmissionDetails($submission_result['details'], "submission-{$submission['id']}-details");
  505. }
  506. ?>
  507. <?= $submissions_pag->pagination() ?>
  508. <?php elseif ($cur_tab === 'click-zan'): ?>
  509. 没写好QAQ
  510. <?php elseif ($cur_tab === 'search'): ?>
  511. <h2 class="text-center">一周搜索情况</h2>
  512. <div id="search-distribution-chart-week" style="height: 250px;"></div>
  513. <script type="text/javascript">
  514. new Morris.Line({
  515. element: 'search-distribution-chart-week',
  516. data: <?= json_encode(DB::selectAll("select DATE_FORMAT(created_at, '%Y-%m-%d %h:00'), count(*) from search_requests where created_at > now() - interval 1 week group by DATE_FORMAT(created_at, '%Y-%m-%d %h:00')")) ?>,
  517. xkey: "DATE_FORMAT(created_at, '%Y-%m-%d %h:00')",
  518. ykeys: ["count(*)"],
  519. labels: ['number'],
  520. resize: true
  521. });
  522. </script>
  523. <h2 class="text-center">一月搜索情况</h2>
  524. <div id="search-distribution-chart-month" style="height: 250px;"></div>
  525. <script type="text/javascript">
  526. new Morris.Line({
  527. element: 'search-distribution-chart-month',
  528. data: <?= json_encode(DB::selectAll("select DATE_FORMAT(created_at, '%Y-%m-%d'), count(*) from search_requests where created_at > now() - interval 1 week group by DATE_FORMAT(created_at, '%Y-%m-%d')")) ?>,
  529. xkey: "DATE_FORMAT(created_at, '%Y-%m-%d')",
  530. ykeys: ["count(*)"],
  531. labels: ['number'],
  532. resize: true
  533. });
  534. </script>
  535. <?php echoLongTable(array('*'), 'search_requests', "1", 'order by id desc',
  536. '<tr><th>id</th><th>created_at</th><th>remote_addr</th><th>type</th><th>q</th><tr>',
  537. function($row) {
  538. echo '<tr>';
  539. echo '<td>', $row['id'], '</td>';
  540. echo '<td>', $row['created_at'], '</td>';
  541. echo '<td>', $row['remote_addr'], '</td>';
  542. echo '<td>', $row['type'], '</td>';
  543. echo '<td>', HTML::escape($row['q']), '</td>';
  544. echo '</tr>';
  545. }, array(
  546. 'page_len' => 1000
  547. ))
  548. ?>
  549. <?php elseif ($cur_tab === 'judger'): ?>
  550. <div>
  551. <h4>添加评测机</h4>
  552. <?php $judger_adder->printHTML(); ?>
  553. </div>
  554. <div>
  555. <h4>删除评测机</h4>
  556. <?php $judger_deleter->printHTML(); ?>
  557. </div>
  558. <h3>评测机列表</h3>
  559. <?php echoLongTable($judgerlist_cols, 'judger_info', "1=1", '', $judgerlist_header_row, $judgerlist_print_row, $judgerlist_config) ?>
  560. <?php elseif ($cur_tab === 'paste'): ?>
  561. <div>
  562. <h4>Paste管理</h4>
  563. <?php echoPastesList() ?>
  564. </div>
  565. <?php elseif ($cur_tab == 'groups'): ?>
  566. <div>
  567. <h4>用户组管理</h4>
  568. <?php echoGroupsList() ?>
  569. </div>
  570. <div>
  571. <h4>添加用户到组</h4>
  572. <?php $user_attach_form->printHTML(); ?>
  573. </div>
  574. <div>
  575. <h4>添加题目到组</h4>
  576. <?php $problem_attach_form->printHTML(); ?>
  577. </div>
  578. <?php elseif ($cur_tab == 'certs'): ?>
  579. <div>
  580. <h4>将勋章授予某人</h4>
  581. <?php $assign_certs_form->printHTML(); ?>
  582. </div>
  583. <?php endif ?>
  584. </div>
  585. </div>
  586. <?php echoUOJPageFooter() ?>