| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- <?php
- // Shared sidebar for the blog archive (/blog/<user>) and the blog post page
- // (/blog/<user>/post/<id>).
- //
- // Expects:
- // $owner blog owner's username
- // $show_write_buttons render the "写新博客 / 写新幻灯片" buttons (owner only)
- // $show_tags render the 标签 card (archive page only)
- // $all_tags tags for the 标签 card (rows with a 'tag' key)
- if (!isset($owner)) {
- $owner = UOJContext::userid();
- }
- $show_write_buttons = !empty($show_write_buttons);
- $show_tags = !empty($show_tags);
- if (!isset($all_tags)) {
- $all_tags = array();
- }
- $sidebar_user = queryUser($owner);
- // Queried exactly once per page view; the mini preview and the enlarged
- // modal both render from this single map.
- $activity = queryUserActivityHeatmap($owner);
- $heatmap_today_ts = strtotime(date('Y-m-d'));
- // Sunday of the current week (weeks are Monday-first), then back up to the
- // Monday 52 weeks before it: 53 columns x 7 rows ending at today.
- $heatmap_start_ts = $heatmap_today_ts + (7 - (int)date('N', $heatmap_today_ts)) * 86400 - 370 * 86400;
- // Month labels are only shown in the enlarged modal, spaced at least four
- // columns apart so short month names never overlap; a partial leading month
- // yields to the fuller month that starts right after it.
- $heatmap_month_labels = array();
- $heatmap_candidates = array();
- $heatmap_prev_month = null;
- for ($col = 0; $col < 53; $col++) {
- $month = (int)date('n', $heatmap_start_ts + $col * 7 * 86400);
- if ($month !== $heatmap_prev_month) {
- $heatmap_candidates[] = array($col, $month.'月');
- $heatmap_prev_month = $month;
- }
- }
- $heatmap_last_col = -100;
- foreach ($heatmap_candidates as $candidate) {
- if ($candidate[0] - $heatmap_last_col < 4) {
- array_pop($heatmap_month_labels);
- }
- $heatmap_month_labels[$candidate[0]] = $candidate[1];
- $heatmap_last_col = $candidate[0];
- }
- ksort($heatmap_month_labels);
- // Build the 371 cells once and reuse the same markup in both grids.
- $heatmap_cells = '';
- for ($col = 0; $col < 53; $col++) {
- for ($row = 0; $row < 7; $row++) {
- $ts = $heatmap_start_ts + ($col * 7 + $row) * 86400;
- $date = date('Y-m-d', $ts);
- $count = isset($activity[$date]) ? $activity[$date] : 0;
- if ($count <= 0) {
- $level = 0;
- } elseif ($count == 1) {
- $level = 1;
- } elseif ($count == 2) {
- $level = 2;
- } elseif ($count == 3) {
- $level = 3;
- } else {
- $level = 4;
- }
- if ($ts > $heatmap_today_ts) {
- $heatmap_cells .= '<span class="wyoj-heatmap-cell wyoj-heatmap-cell-future" data-level="0" data-date="'.$date.'" data-count="0"></span>';
- } else {
- $heatmap_cells .= '<span class="wyoj-heatmap-cell" data-level="'.$level.'" data-date="'.$date.'" data-count="'.$count.'" title="'.$count.' 次 · '.$date.'"></span>';
- }
- }
- }
- $heatmap_total = array_sum($activity);
- ?>
- <div class="wyoj-blog-sidebar">
- <?php if ($show_write_buttons && UOJContext::hasBlogPermission()): ?>
- <div class="btn-group d-flex">
- <a href="<?= HTML::blog_url($owner, '/post/new/write') ?>" class="btn btn-primary"><span class="glyphicon glyphicon-edit"></span> 写新博客</a>
- <a href="<?= HTML::blog_url($owner, '/slide/new/write') ?>" class="btn btn-primary"><span class="glyphicon glyphicon-edit"></span> 写新幻灯片</a>
- </div>
- <?php endif ?>
- <div class="card top-buffer-sm wyoj-blog-owner-card">
- <div class="card-body">
- <img class="wyoj-blog-owner-avatar" src="<?= HTML::avatar_addr($sidebar_user, 256) ?>" alt="<?= HTML::escape($owner) ?> Avatar" />
- <div class="wyoj-blog-owner-name"><a href="<?= HTML::url('/user/profile/'.$owner) ?>"><?= HTML::escape($owner) ?></a></div>
- <div class="wyoj-blog-owner-motto text-muted"><?= HTML::escape($sidebar_user['motto']) ?></div>
- </div>
- </div>
- <?php if ($show_tags): ?>
- <div class="card top-buffer-sm">
- <div class="card-header">标签</div>
- <div class="card-body">
- <?php if ($all_tags): ?>
- <?php foreach ($all_tags as $tag): ?>
- <?php echoBlogTag($tag['tag']) ?>
- <?php endforeach ?>
- <?php else: ?>
- <div class="text-muted">暂无</div>
- <?php endif ?>
- </div>
- </div>
- <?php endif ?>
- <div class="card top-buffer-sm wyoj-heatmap-card" id="wyoj-heatmap-preview" role="button" tabindex="0" aria-label="查看全年活跃度">
- <div class="card-header d-flex justify-content-between align-items-center">
- <span>活跃度</span>
- <small class="text-muted">近 53 周</small>
- </div>
- <div class="card-body">
- <div class="wyoj-heatmap-mini">
- <div class="wyoj-heatmap-grid wyoj-heatmap-grid-mini"><?= $heatmap_cells ?></div>
- </div>
- <div class="wyoj-heatmap-hint text-muted"><span class="glyphicon glyphicon-zoom-in"></span> 查看全年</div>
- </div>
- </div>
- </div>
- <div class="uoj-modal wyoj-heatmap-modal" id="wyoj-heatmap-modal" hidden>
- <div class="uoj-modal-backdrop" data-uoj-modal-close></div>
- <div class="uoj-modal-window" role="dialog" aria-modal="true" aria-label="活跃度">
- <button type="button" class="uoj-modal-close" data-uoj-modal-close aria-label="关闭">×</button>
- <div class="uoj-modal-body">
- <div class="wyoj-heatmap-modal-head">
- <span class="wyoj-heatmap-modal-title">活跃度</span>
- <small class="text-muted">近 53 周<?= $heatmap_total > 0 ? ' · 共 '.$heatmap_total.' 次' : '' ?></small>
- </div>
- <?php if ($heatmap_total <= 0): ?>
- <div class="text-muted top-buffer-sm">暂无活跃记录</div>
- <?php endif ?>
- <div class="wyoj-heatmap-lg-wrap">
- <div class="wyoj-heatmap-lg">
- <div class="wyoj-heatmap-lg-corner"></div>
- <div class="wyoj-heatmap-months wyoj-heatmap-months-lg">
- <?php foreach ($heatmap_month_labels as $col => $label): ?>
- <span style="grid-column: <?= $col + 1 ?>"><?= $label ?></span>
- <?php endforeach ?>
- </div>
- <div class="wyoj-heatmap-lg-days">
- <span style="grid-row: 1">一</span>
- <span style="grid-row: 3">三</span>
- <span style="grid-row: 5">五</span>
- </div>
- <div class="wyoj-heatmap-grid wyoj-heatmap-grid-lg"><?= $heatmap_cells ?></div>
- </div>
- </div>
- <div class="wyoj-heatmap-legend wyoj-heatmap-legend-lg">
- <span class="wyoj-heatmap-cell" data-level="0"></span>
- <span class="wyoj-heatmap-cell" data-level="1"></span>
- <span class="wyoj-heatmap-cell" data-level="2"></span>
- <span class="wyoj-heatmap-cell" data-level="3"></span>
- <span class="wyoj-heatmap-cell" data-level="4"></span>
- <span class="wyoj-heatmap-legend-label">活跃程度</span>
- </div>
- </div>
- </div>
- </div>
- <?php echoUOJModalHelper(); ?>
- <script type="text/javascript">
- (function () {
- var card = document.getElementById('wyoj-heatmap-preview');
- var modal = document.getElementById('wyoj-heatmap-modal');
- if (!card || !modal || !window.uojModalInit) {
- return;
- }
- var api = window.uojModalInit(modal);
- function openModal(e) {
- e.preventDefault();
- api.open();
- }
- card.addEventListener('click', openModal);
- card.addEventListener('keydown', function (e) {
- if (e.key === 'Enter' || e.key === ' ' || e.keyCode === 13 || e.keyCode === 32) {
- openModal(e);
- }
- });
- })();
- </script>
|