S2OJ/web/app/views/user-info.php

350 lines
13 KiB
PHP
Raw Normal View History

2022-11-06 02:26:21 +00:00
<?php $extra = UOJUser::getExtra($user); ?>
2022-10-04 08:31:08 +00:00
2022-10-02 12:47:53 +00:00
<div class="row">
<div class="col-md-3">
<div class="card">
2023-02-07 11:36:48 +00:00
<img class="card-img-top uoj-user-avatar" alt="Avatar of <?= $user['username'] ?>" src="<?= HTML::avatar_addr($user, 512) ?>" />
2022-10-02 12:47:53 +00:00
<div class="card-body">
2022-11-11 00:20:33 +00:00
<?php if ($user['usergroup'] == 'S') : ?>
<span class="badge bg-secondary">
<?= UOJLocale::get('user::admin') ?>
</span>
2022-10-02 12:47:53 +00:00
<?php endif ?>
<h3>
<?= $user['username'] ?>
2022-11-11 00:20:33 +00:00
<span class="fs-6 align-middle" <?php if ($user['sex'] == 'M') : ?> style="color: blue"><i class="bi bi-gender-male"></i>
<?php elseif ($user['sex'] == 'F') : ?>
2022-10-02 12:47:53 +00:00
style="color: red"><i class="bi bi-gender-female"></i>
2022-11-11 00:20:33 +00:00
<?php else : ?>
2022-10-20 13:51:46 +00:00
>
2022-10-02 12:47:53 +00:00
<?php endif ?>
</span>
</h3>
<div class="card-text">
2023-01-15 03:13:43 +00:00
<?= HTML::purifier_inline()->purify(HTML::parsedown(['username_with_color' => true])->line($user['motto'])) ?>
</div>
2022-10-02 12:47:53 +00:00
</div>
<ul class="list-group list-group-flush">
2022-11-12 01:21:36 +00:00
<li class="list-group-item">
<i class="bi bi-person-fill me-1"></i>
<?= $user['realname'] ?>
<?php if ($user['realname']) : ?>
<span class="small text-secondary">
(<?= UOJLocale::get('user::' . $user['usertype']) ?: HTML::escape($user['usertype']) ?>)
</span>
<?php else : ?>
<span class="text-secondary">
<?= UOJLocale::get('user::' . $user['usertype']) ?: HTML::escape($user['usertype']) ?>
</span>
<?php endif ?>
</li>
2022-11-11 00:20:33 +00:00
<?php if ($user['school']) : ?>
<li class="list-group-item">
<i class="bi bi-person-badge-fill me-1"></i>
<?= $user['school'] ?>
</li>
2022-10-02 12:47:53 +00:00
<?php endif ?>
2022-11-11 00:20:33 +00:00
<?php if ($user['email']) : ?>
<li class="list-group-item">
<i class="bi bi-envelope-fill me-1"></i>
<a class="text-decoration-none text-body" href="mailto:<?= HTML::escape($user['email']) ?>">
<?= HTML::escape($user['email']) ?>
</a>
</li>
2022-10-20 00:44:55 +00:00
<?php endif ?>
2022-11-11 00:20:33 +00:00
<?php if ($user['qq']) : ?>
<li class="list-group-item">
2022-11-12 01:21:36 +00:00
<i class="align-text-bottom me-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="16" height="16">
2022-11-11 00:20:33 +00:00
<path d="M433.754 420.445c-11.526 1.393-44.86-52.741-44.86-52.741 0 31.345-16.136 72.247-51.051 101.786 16.842 5.192 54.843 19.167 45.803 34.421-7.316 12.343-125.51 7.881-159.632 4.037-34.122 3.844-152.316 8.306-159.632-4.037-9.045-15.25 28.918-29.214 45.783-34.415-34.92-29.539-51.059-70.445-51.059-101.792 0 0-33.334 54.134-44.859 52.741-5.37-.65-12.424-29.644 9.347-99.704 10.261-33.024 21.995-60.478 40.144-105.779C60.683 98.063 108.982.006 224 0c113.737.006 163.156 96.133 160.264 214.963 18.118 45.223 29.912 72.85 40.144 105.778 21.768 70.06 14.716 99.053 9.346 99.704z" fill="currentColor" />
2022-11-12 01:21:36 +00:00
</svg>
</i>
2022-11-11 00:20:33 +00:00
<a class="text-decoration-none text-body" href="http://wpa.qq.com/msgrd?v=3&uin=<?= HTML::escape($user['qq']) ?>&site=qq&menu=yes" target="_blank">
<?= HTML::escape($user['qq']) ?>
</a>
</li>
2022-10-20 00:44:55 +00:00
<?php endif ?>
2022-11-11 00:20:33 +00:00
<?php if ($extra['social']['github']) : ?>
<li class="list-group-item">
<i class="bi bi-github me-1"></i>
<a class="text-decoration-none text-body" href="https://github.com/<?= HTML::escape($extra['social']['github']) ?>" target="_blank">
<?= HTML::escape($extra['social']['github']) ?>
2022-10-20 00:44:55 +00:00
</a>
2022-11-11 00:20:33 +00:00
</li>
<?php endif ?>
<?php if ($extra['social']['codeforces']) : ?>
<li class="list-group-item d-flex align-items-center">
2022-11-12 01:21:36 +00:00
<div class="flex-shrink-0">
<i class="align-text-bottom me-1">
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" width="16" height="16">
2022-11-11 00:20:33 +00:00
<title>Codeforces</title>
<path d="M4.5 7.5C5.328 7.5 6 8.172 6 9v10.5c0 .828-.672 1.5-1.5 1.5h-3C.673 21 0 20.328 0 19.5V9c0-.828.673-1.5 1.5-1.5h3zm9-4.5c.828 0 1.5.672 1.5 1.5v15c0 .828-.672 1.5-1.5 1.5h-3c-.827 0-1.5-.672-1.5-1.5v-15c0-.828.673-1.5 1.5-1.5h3zm9 7.5c.828 0 1.5.672 1.5 1.5v7.5c0 .828-.672 1.5-1.5 1.5h-3c-.828 0-1.5-.672-1.5-1.5V12c0-.828.672-1.5 1.5-1.5h3z" fill="currentColor" />
2022-11-12 01:21:36 +00:00
</svg>
</i>&nbsp;
</div>
2022-11-11 00:20:33 +00:00
<div>
<a id="codeforces-profile-link" class="text-decoration-none" href="https://codeforces.com/profile/<?= $extra['social']['codeforces'] ?>" target="_blank" style="color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important;">
<?= $extra['social']['codeforces'] ?>
</a>
<div id="codeforces-rating" style="font-family: verdana, arial, sans-serif; line-height: 1.2em; text-transform: capitalize;"></div>
</div>
<script>
function getRatingColor(rating) {
if (rating >= 2400) return 'ff0000';
if (rating >= 2100) return 'ff8c00';
if (rating >= 1900) return 'aa00aa';
if (rating >= 1600) return '0000ff';
if (rating >= 1400) return '03a89e';
if (rating >= 1200) return '008000';
return '808080';
}
2022-10-20 00:44:55 +00:00
2022-11-11 00:20:33 +00:00
function showCodeforcesRating(handle, rating, text) {
var color = '#' + getRatingColor(rating);
2022-10-20 00:44:55 +00:00
2022-11-11 00:20:33 +00:00
$('#codeforces-profile-link')
.html(rating >= 3000 ? ('<span style="color:#000!important">' + handle[0] + '</span>' + handle.substring(1)) : handle)
.css('color', color)
.css('font-family', 'Helvetica Neue, Helvetica, Arial, sans-serif')
.css('font-size', '1.1em')
.css('font-weight', 'bold');
$('#codeforces-rating')
.html(text + ', ' + rating)
.css('color', color);
}
2022-10-20 00:44:55 +00:00
2022-11-11 00:20:33 +00:00
function processCodeforcesInfoData(data) {
if (!data || data.status !== 'OK' || !data.result || !data.result.length) return;
2022-10-20 00:44:55 +00:00
2022-11-11 00:20:33 +00:00
var result = data.result[0];
if (result.rating) {
showCodeforcesRating(result.handle, result.rating, result.rank);
} else {
showCodeforcesRating(result.handle, 0, 'Unrated');
}
2022-10-20 00:44:55 +00:00
}
2022-11-11 00:20:33 +00:00
$(document).ready(function() {
$.get('https://codeforces.com/api/user.info?handles=<?= $extra['social']['codeforces'] ?>', function(data) {
processCodeforcesInfoData(data);
});
2022-11-06 02:26:21 +00:00
});
2022-11-11 00:20:33 +00:00
</script>
</li>
2022-10-02 12:47:53 +00:00
<?php endif ?>
2022-11-11 00:20:33 +00:00
<?php if ($extra['social']['website']) : ?>
<li class="list-group-item">
<i class="bi bi-link-45deg me-1"></i>
<a class="text-decoration-none text-body text-break" href="<?= HTML::escape($extra['social']['website']) ?>" target="_blank">
<?= HTML::escape($extra['social']['website']) ?>
</a>
</li>
2022-10-20 00:45:23 +00:00
<?php endif ?>
2022-10-02 12:47:53 +00:00
</ul>
2022-10-04 08:31:08 +00:00
<div class="card-footer bg-transparent">
<?php $last_visit_time = UOJTime::str2time($user['last_visit_time']) ?>
<?php if ((clone UOJTime::$time_now)->modify('- 15 mins') <= $last_visit_time) : ?>
2022-10-04 08:42:59 +00:00
<span class="text-success">
2022-10-06 03:38:10 +00:00
<i class="bi bi-circle-fill me-1"></i>
2022-10-20 00:44:55 +00:00
<?= UOJLocale::get('user::online') ?>
2022-10-04 08:31:08 +00:00
</span>
2022-11-11 00:20:33 +00:00
<?php else : ?>
2022-10-04 08:42:59 +00:00
<span class="text-danger">
2022-10-06 03:38:10 +00:00
<i class="bi bi-circle-fill me-1"></i>
2022-10-20 00:44:55 +00:00
<?= UOJLocale::get('user::offline') ?>
2022-10-04 08:31:08 +00:00
</span>
2022-11-11 00:20:33 +00:00
<?php if ($last_visit_time > 0) : ?>
2022-10-05 02:58:05 +00:00
<span class="text-muted small">
2022-11-11 00:20:33 +00:00
(<?= UOJLocale::get('user::last active at') ?>
<?php if ((clone UOJTime::$time_now)->modify('- 1 day') <= $last_visit_time) : ?>
<?= HTML::relative_time_str($last_visit_time->getTimestamp(), 0) ?>)
<?php else : ?>
<?= $last_visit_time->format('Y-m-d') ?>)
<?php endif ?>
2022-10-04 08:42:59 +00:00
</span>
<?php endif ?>
2022-10-04 08:31:08 +00:00
<?php endif ?>
</div>
2022-10-02 12:47:53 +00:00
</div>
</div>
<div class="col-md-9 mt-2 mt-md-0">
<nav class="nav mb-2">
2022-11-11 00:20:33 +00:00
<?php if (Auth::check()) : ?>
<?php if (Auth::id() != $user['username']) : ?>
<a class="nav-link" href="/user_msg?enter=<?= $user['username'] ?>">
2022-10-02 12:47:53 +00:00
<i class="bi bi-chat-left-dots"></i>
<?= UOJLocale::get('send private message') ?>
</a>
<?php endif ?>
2022-11-11 00:20:33 +00:00
<?php if (Auth::id() == $user['username'] || isSuperUser(Auth::user())) : ?>
<a class="nav-link" href="/user/<?= $user['username'] ?>/edit">
2022-10-02 12:47:53 +00:00
<i class="bi bi-pencil"></i>
<?= UOJLocale::get('modify my profile') ?>
</a>
<?php endif ?>
<?php endif ?>
2022-11-11 00:20:33 +00:00
<?php if (!isset($is_blog_aboutme)) : ?>
<a class="nav-link" href="<?= HTML::blog_url($user['username'], '/') ?>">
<i class="bi bi-arrow-right-square"></i>
<?= UOJLocale::get('visit his blog', $user['username']) ?>
</a>
<a class="nav-link" href="<?= HTML::blog_url($user['username'], '/self_reviews') ?>">
<i class="bi bi-arrow-right-square"></i>
<?= UOJLocale::get('contests::contest self reviews') ?>
</a>
2022-11-06 02:26:21 +00:00
<?php endif ?>
2022-10-02 12:47:53 +00:00
</nav>
2022-11-11 00:20:33 +00:00
<?php if (!isset($is_blog_aboutme)) : ?>
2022-11-11 23:10:34 +00:00
<?php $groups = UOJGroup::queryGroupsOfUser($user) ?>
2022-11-11 00:20:33 +00:00
<div class="card mb-2">
2023-02-14 14:08:41 +00:00
<div class="card-header fw-bold">
<?= UOJLocale::get('user::belongs to these groups') ?>
</div>
<ul class="list-group list-group-flush">
<?php foreach ($groups as $group) : ?>
<li class="list-group-item">
<?= $group->getLink(['class' => 'fw-bold']) ?>
</li>
<?php endforeach ?>
<?php if (empty($groups)) : ?>
<li class="list-group-item text-center">
2022-11-11 00:20:33 +00:00
<?= UOJLocale::get('none') ?>
2023-02-14 14:08:41 +00:00
</li>
<?php endif ?>
</ul>
</div>
<?php endif ?>
<?php if (isset($extra['acm'])) : ?>
<div class="card mb-2">
<div class="card-header fw-bold">ACM 队伍信息</div>
<div class="list-group list-group-flush">
<?php foreach ($extra['acm']['members'] as $mem) : ?>
<li class="list-group-item">
<b><?= HTML::escape($mem['name']) ?></b><?= HTML::escape($mem['organization']) ?>
</li>
<?php endforeach ?>
2022-11-11 00:20:33 +00:00
</div>
</div>
2022-10-20 02:51:56 +00:00
<?php endif ?>
2023-02-14 14:08:41 +00:00
<?php if (isSuperUser(Auth::user())) : ?>
<div class="card mb-2">
<div class="card-header fw-bold">超级管理员可见信息</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">
<div class="fw-bold mb-2">注册时间</div>
<?= $user['register_time'] ?>
</li>
<li class="list-group-item">
<div class="fw-bold mb-2">最后一次登录的 IP (remote_addr)</div>
<?= $user['remote_addr'] ?>
</li>
<li class="list-group-item">
<div class="fw-bold mb-2">最后一次登录的 IP (http_x_forwarded_for)</div>
<?= $user['http_x_forwarded_for'] ?>
</li>
<li class="list-group-item">
<div class="fw-bold mb-2">最后一次登录时间</div>
<?= $user['last_login_time'] ?>
</li>
<li class="list-group-item">
<div class="fw-bold mb-2">最后一次上线时间</div>
<?= $user['last_visit_time'] ?>
</li>
<li class="list-group-item">
<div class="fw-bold mb-2">过期时间</div>
<?= $user['expiration_time'] ?: '永不过期' ?>
</li>
<li class="list-group-item">
<div class="fw-bold mb-2">最近访问时使用的 IP 和终端</div>
<dl class="row">
<?php foreach ($extra['history'] as $vis) : ?>
<dt class="col-sm-3"><?= HTML::escape($vis['last']) ?></dt>
<dd class="col-sm-9">
<b>addr</b>: <?= HTML::escape($vis['addr']) ?>
<br>
<b>forwarded_addr</b>: <?= HTML::escape($vis['forwarded_addr']) ?>
<br>
<b>user_agent</b>: <?= HTML::escape($vis['ua']) ?>
</dd>
<?php endforeach ?>
</dl>
</li>
</ul>
</div>
<?php endif ?>
<?php
$ac_records = DB::selectAll([
"select", DB::fields([
2023-02-14 14:08:41 +00:00
"submit_time" => "date_format(submit_time, '%Y-%m-%d')",
"problem_id",
]),
"from submissions",
"where", [
"submitter" => $user['username'],
"score" => 100,
["date(submit_time)", "between", DB::raw("date_sub(curdate(), interval 1 year) and curdate()")],
]
]);
$last_year_ac_cnt_by_day = [];
foreach ($ac_records as $record) {
$last_year_ac_cnt_by_day[$record["submit_time"]]++;
}
?>
2022-10-20 02:51:56 +00:00
<div class="card mb-2">
<div class="card-header fw-bold"><?= UOJLocale::get('n accepted in last year', count($ac_records)) ?></div>
2022-10-02 12:47:53 +00:00
<div class="card-body">
<div id="accepted-graph" style="font-size: 14px"></div>
<script>
var accepted_graph_data = [
2023-02-14 14:08:41 +00:00
<?php foreach ($last_year_ac_cnt_by_day as $key => $val) : ?> {
2022-11-11 00:20:33 +00:00
date: '<?= $key ?>',
count: <?= $val ?>
},
2022-10-02 12:47:53 +00:00
<?php endforeach ?>
];
2022-11-11 00:20:33 +00:00
$(document).ready(function() {
2022-10-02 12:47:53 +00:00
$('#accepted-graph').CalendarHeatmap(accepted_graph_data, {});
});
</script>
</div>
</div>
2023-02-14 14:08:41 +00:00
<?php $ac_problems = DB::selectAll("select problem_id from best_ac_submissions where submitter = '{$user['username']}' order by problem_id") ?>
2022-10-20 02:51:56 +00:00
<div class="card mb-2">
2023-02-14 14:08:41 +00:00
<div class="card-header fw-bold">
<?= UOJLocale::get('accepted problems') . ': ' . UOJLocale::get('n problems in total', count($ac_problems)) ?>
</div>
2022-11-11 00:20:33 +00:00
<div class="card-body">
<ul class="nav uoj-ac-problems-list">
2023-02-13 03:57:10 +00:00
<?php foreach ($ac_problems as $prob) : ?>
<?php $problem = UOJProblem::query($prob['problem_id']) ?>
<?php if ($problem->userCanView(Auth::user())) : ?>
<li class="nav-item">
<?= $problem->getLink(['with' => 'id', 'class' => 'nav-link rounded uoj-ac-problems-list-item']) ?>
</li>
<?php else : ?>
<li class="nav-item">
<a class="nav-link disabled rounded" role="button">
#<?= $problem->info['id'] ?>. 隐藏的题目
</a>
</li>
<?php endif ?>
2022-11-11 00:20:33 +00:00
<?php endforeach ?>
2022-10-02 12:47:53 +00:00
2022-11-11 00:20:33 +00:00
<?php if (empty($ac_problems)) : ?>
<?= UOJLocale::get('none'); ?>
<?php endif ?>
</ul>
</div>
2022-10-02 12:47:53 +00:00
</div>
</div>
</div>