feat: edit contest self reviews

This commit is contained in:
Baoshuo Ren 2022-09-20 07:49:45 +08:00
parent b0773acab8
commit 945bd35776
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
5 changed files with 129 additions and 50 deletions

View File

@ -283,6 +283,56 @@
} else {
$reply_question = null;
}
} elseif ($cur_tab == 'self_reviews') {
if (hasParticipated(Auth::user(), $contest)) {
$self_reviews_update_form = new UOJForm('self_review_update');
$self_reviews_update_form->ctrl_enter_submit = true;
$contest_problems = DB::selectAll("select problem_id from contests_problems where contest_id = {$contest['id']} order by dfn, problem_id");
for ($i = 0; $i < count($contest_problems); $i++) {
$contest_problems[$i]['problem'] = queryProblemBrief($contest_problems[$i]['problem_id']);
}
for ($i = 0; $i < count($contest_problems); $i++) {
$content = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = {$contest_problems[$i]['problem_id']} and poster = '{$myUser['username']}'")['content'];
$self_reviews_update_form->addVTextArea('self_review_update__problem_' . chr(ord('A') + $i), '<b>' . chr(ord('A') + $i) . '</b>: ' . $contest_problems[$i]['problem']['title'], $content,
function ($content) {
return '';
},
null,
true
);
}
$content = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = -1 and poster = '{$myUser['username']}'")['content'];
$self_reviews_update_form->addVTextArea('self_review_update__overall', '比赛总结', $content,
function ($content) {
return '';
},
null,
true
);
$self_reviews_update_form->handle = function() {
global $contest, $contest_problems, $myUser;
for ($i = 0; $i < count($contest_problems); $i++) {
if (isset($_POST['self_review_update__problem_' . chr(ord('A') + $i)])) {
$esc_content = DB::escape($_POST['self_review_update__problem_' . chr(ord('A') + $i)]);
$problem_id = $contest_problems[$i]['problem_id'];
DB::query("replace into contests_reviews (contest_id, problem_id, poster, content) values ({$contest['id']}, $problem_id, '{$myUser['username']}', '$esc_content')");
}
}
if (isset($_POST['self_review_update__overall'])){
$esc_content = DB::escape($_POST['self_review_update__overall']);
DB::query("replace into contests_reviews (contest_id, problem_id, poster, content) values ({$contest['id']}, -1, '{$myUser['username']}', '$esc_content')");
}
};
$self_reviews_update_form->runAtServer();
}
}
function echoDashboard() {
@ -517,7 +567,7 @@ EOD;
echoContestFinished();
}
?>
<?php if ($cur_tab == 'standings' || $cur_tab == 'after_contest_standings'): ?>
<?php if ($cur_tab == 'standings' || $cur_tab == 'after_contest_standings' || $cur_tab == 'self_reviews'): ?>
</div>
<div class="col-sm-3">
<?php endif ?>
@ -543,8 +593,12 @@ EOD;
</div>
<?php endif ?>
<?php endif ?>
<?php if ($contest['extra_config']['links']) { ?>
<?php if (isset($self_reviews_update_form)) { ?>
</div>
<div class="col-sm-6">
<h4>修改我的赛后总结</h4>
<?php $self_reviews_update_form->printHTML(); ?>
<?php } elseif ($contest['extra_config']['links'] && $cur_tab != 'self_reviews') { ?>
<?php if ($cur_tab == 'standings'): ?>
</div>
<div class="col-sm-3">

View File

@ -109,12 +109,20 @@ function calcStandings($contest, $contest_data, &$score, &$standings, $update_co
}
$score[$submission[2]][$submission[3]] = array($submission[4], $penalty, $submission[0]);
}
if ($show_reviews) {
$review_result = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = {$contest_data['problems'][$submission[3]]} and poster = '{$person[0]}'");
foreach ($contest_data['people'] as $person) {
foreach ($contest_data['problems'] as $key => $problem) {
$review_result = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = {$problem} and poster = '{$person[0]}'");
if (!isset($score[$person[0]][$key])) {
$score[$person[0]][$key] = array(0, 0, 0);
}
if ($review_result['content']) {
$score[$submission[2]][$submission[3]][] = $review_result['content'];
$score[$person[0]][$key][] = $review_result['content'];
}
}
}
}
@ -135,7 +143,7 @@ function calcStandings($contest, $contest_data, &$score, &$standings, $update_co
}
if ($show_reviews) {
$review_result = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and poster = '{$person[0]}'");
$review_result = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = -1 and poster = '{$person[0]}'");
if ($review_result['content']) {
$cur[] = $review_result['content'];

View File

@ -71,12 +71,18 @@
$this->ajax_submit_js = $js;
}
public function add($name, $html, $validator_php, $validator_js) {
public function add($name, $html, $validator_php, $validator_js, $no_val = false) {
$this->main_html .= $html;
$this->data[] = array(
$data = array(
'name' => $name,
'validator_php' => $validator_php,
'validator_js' => $validator_js);
if ($no_val) {
$data['no_val'] = '';
}
$this->data[] = $data;
}
public function appendHTML($html) {
$this->main_html .= $html;
@ -183,7 +189,7 @@ EOD;
);
}
public function addTextArea($name, $label_text, $default_value, $validator_php, $validator_js) {
public function addTextArea($name, $label_text, $default_value, $validator_php, $validator_js, $no_val = false) {
$default_value = htmlspecialchars($default_value);
$this->is_big = true;
$html = <<<EOD
@ -195,9 +201,9 @@ EOD;
</div>
</div>
EOD;
$this->add($name, $html, $validator_php, $validator_js);
$this->add($name, $html, $validator_php, $validator_js, $no_val);
}
public function addVTextArea($name, $label_text, $default_value, $validator_php, $validator_js) {
public function addVTextArea($name, $label_text, $default_value, $validator_php, $validator_js, $no_val = false) {
$default_value = htmlspecialchars($default_value);
$this->is_big = true;
$html = <<<EOD
@ -207,7 +213,7 @@ EOD;
<span class="help-block" id="help-$name"></span>
</div>
EOD;
$this->add($name, $html, $validator_php, $validator_js);
$this->add($name, $html, $validator_php, $validator_js, $no_val);
}
public function addCheckBox($name, $label_text, $default_value) {
$default_value = htmlspecialchars($default_value);

View File

@ -41,6 +41,11 @@ function hasRegistered($user, $contest) {
function hasAC($user, $problem) {
return DB::selectFirst("select * from best_ac_submissions where submitter = '${user['username']}' and problem_id = ${problem['id']}") != null;
}
function hasParticipated($user, $contest) {
$result = DB::selectFirst("select * from contests_registrants where username = '${user['username']}' and contest_id = ${contest['id']}");
return $result != null && $result['has_participated'];
}
function queryUser($username) {
if (!validateUsername($username)) {

View File

@ -1079,10 +1079,24 @@ function showStandings() {
col_tr += '<td>' + getUserLink(row[2][0], row[2][1]) + '</td>';
col_tr += '<td>' + '<div><span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span></div>' + '<div>' + getPenaltyTimeStr(row[1]) + '</div></td>';
for (var i = 0; i < problems.length; i++) {
col_tr += '<td>';
col_tr += '<td' + (show_self_reviews ? ' style="vertical-align: text-top"' : '') + '>';
col = score[row[2][0]][i];
if (col != undefined) {
col_tr += '<div><a href="/submission/' + col[2] + '" class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</a></div>';
col_tr += '<div>';
if (col[2]) col_tr += '<a href="/submission/' + col[2] + '" class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</a>';
else col_tr += '<span class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</span>';
col_tr += '</div>';
if (show_self_reviews) {
col_tr += '<div id="review-' + row[2][0] + '-' + i + '"></div>'
+ '<script>'
+ '$(function() {'
+ 'var purify_result = DOMPurify.sanitize(decodeURIComponent("' + encodeURIComponent(String(col[3] || '')) + '"), {ALLOWED_TAGS: ["a", "b", "i", "u", "em", "strong", "sub", "sup", "small", "del", "br"], ALLOWED_ATTR: ["href"]});'
+ '$("#review-' + row[2][0] + '-' + i + '")'
+ '.html(purify_result ? \'<div class="mt-2 pt-2 border-top">\' + purify_result + \'</div>\' : \'\'); });'
+ '</scr' + 'ipt>';
} else {
if (standings_version < 2) {
col_tr += '<div>' + getPenaltyTimeStr(col[1]) + '</div>';
} else {
@ -1090,14 +1104,6 @@ function showStandings() {
col_tr += '<div>' + getPenaltyTimeStr(col[1]) + '</div>';
}
}
if (show_self_reviews) {
col_tr += '<div id="review-' + row[2][0] + '-' + i + '"></div>'
+ '<script>'
+ '$(function() {'
+ 'var purify_result = DOMPurify.sanitize(\'' + String(col[3] || '').replace(/'/g, '\\\'').replace(new RegExp('</scr' + 'ipt>', 'gi'), '</scr\' + \'ipt>') + '\', {ALLOWED_TAGS: ["a", "b", "i", "u", "em", "strong", "sub", "sup", "small", "del"], ALLOWED_ATTR: ["href"]});'
+ '$("#review-' + row[2][0] + '-' + i + '")'
+ '.html(purify_result ? \'<div class="mt-3 pt-2 border-top">\' + purify_result + \'</div>\' : \'\'); });'
+ '</scr' + 'ipt>';
}
}
col_tr += '</td>';
@ -1107,7 +1113,7 @@ function showStandings() {
col_tr += '<td><div id="review-' + row[2][0] + '"></div>'
+ '<script>'
+ '$(function() { $("#review-' + row[2][0] + '")'
+ '.html(DOMPurify.sanitize(\'' + String(row[4] || '').replace(/'/g, '\\\'').replace(new RegExp('</scr' + 'ipt>', 'gi'), '</scr\' + \'ipt>') + '\', {ALLOWED_TAGS: ["a", "b", "i", "u", "em", "strong", "sub", "sup", "small", "del"], ALLOWED_ATTR: ["href"]})); });'
+ '.html(DOMPurify.sanitize(decodeURIComponent("' + encodeURIComponent(String(row[4] || '')) + '"), {ALLOWED_TAGS: ["a", "b", "i", "u", "em", "strong", "sub", "sup", "small", "del"], ALLOWED_ATTR: ["href"]})); });'
+ '</scr' + 'ipt></td>';
}
col_tr += '</tr>';