mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
ui: scoreboard: virtual-scroll
This commit is contained in:
2 files changed
+75
-47
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import Clusterize from 'clusterize.js';
|
||||
import $ from 'jquery';
|
||||
import { NamedPage } from 'vj/misc/Page';
|
||||
import { pjax } from 'vj/utils';
|
||||
@@ -5,7 +6,7 @@ import { pjax } from 'vj/utils';
|
||||
const page = new NamedPage('contest_scoreboard', () => {
|
||||
const { tdoc } = UiContext;
|
||||
const key = `scoreboard-star/${tdoc.domainId}/${tdoc.docId}`;
|
||||
const read = () => JSON.parse(localStorage.getItem(key) || '[]');
|
||||
const read = () => JSON.parse(localStorage.getItem(key) || '[]').map((i) => +i);
|
||||
const write = (data) => localStorage.setItem(key, JSON.stringify(data));
|
||||
|
||||
read().forEach((uid) => $(`.star.user--${uid}`).addClass('activated'));
|
||||
@@ -23,22 +24,40 @@ const page = new NamedPage('contest_scoreboard', () => {
|
||||
write(star);
|
||||
});
|
||||
|
||||
const rows: Record<number, string> = {};
|
||||
const total = [];
|
||||
let nowRendering = [];
|
||||
const unrank = [];
|
||||
for (const line of $('.data-table tbody tr')) {
|
||||
const uid = +$(line).find('[data-uid]').data('uid');
|
||||
line.style.display = 'table-row';
|
||||
rows[uid] = line.outerHTML;
|
||||
nowRendering.push(uid);
|
||||
total.push(uid);
|
||||
if ($(line).find('.rank--unrank').length) unrank.push(uid);
|
||||
$(line).remove();
|
||||
}
|
||||
|
||||
const virtualizedList = new Clusterize({
|
||||
rows: nowRendering.map((i) => rows[i]),
|
||||
scrollElem: $('.data-table').get(0),
|
||||
contentElem: $('tbody').get(0),
|
||||
});
|
||||
|
||||
$('.select.filter').on('change', (e) => {
|
||||
const val = $(e.target).val();
|
||||
if (val === 'all') {
|
||||
$('.data-table tbody tr').show();
|
||||
} else if (val === 'star') {
|
||||
$('.data-table tbody tr').hide();
|
||||
read().forEach((uid) => $(`.star.user--${uid}`).closest('tr').show());
|
||||
} else if (val === 'rank') {
|
||||
$('.data-table tbody tr').show();
|
||||
$('.rank--unrank').closest('tr').hide();
|
||||
} else {
|
||||
$('.data-table tbody tr').hide();
|
||||
if (val === 'all') nowRendering = total;
|
||||
else if (val === 'star') nowRendering = read();
|
||||
else if (val === 'rank') nowRendering = total.filter((i) => !unrank.includes(i));
|
||||
else {
|
||||
nowRendering = [];
|
||||
const uids = val.toString().split(',').map((i) => +i.trim()).filter((i) => i);
|
||||
if (!uids?.length) return;
|
||||
uids.forEach((uid) => $(`.user--${uid}`).closest('tr').show());
|
||||
for (const uid of total) {
|
||||
if (!uids.includes(+uid)) continue;
|
||||
nowRendering.push(uid);
|
||||
}
|
||||
}
|
||||
virtualizedList.update(nowRendering.map((i) => rows[i]));
|
||||
});
|
||||
|
||||
const beginAt = new Date(UiContext.tdoc.beginAt).getTime();
|
||||
|
||||
@@ -6,6 +6,41 @@
|
||||
</a>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro scoreboardRow(row) %}
|
||||
{%- for column in row -%}
|
||||
<td class="col--{{ rows[0][loop.index0]['type'] }}"{% if column.style %} style="{{ column.style }}"{% endif %}>
|
||||
{%- if column.type == 'rank' -%}
|
||||
<span class="{{ 'rank--unrank' if column.value == '0' else 'rank--normal' }}">{{ '*' if column.value == '0' else column.value|string|nl2br|safe }}</span>
|
||||
{%- elif column.type == 'user' -%}
|
||||
{%- set canView = canViewAll or handler.user._id == column.raw -%}
|
||||
<button class="star user--{{ column.raw }}" data-uid="{{ column.raw }}">
|
||||
<span class="starred--hide"><span class="icon icon-star--outline" data-tooltip="{{ _('Star') }}"></span></span>
|
||||
<span class="starred--show"><span class="icon icon-star" data-tooltip="{{ _('Unstar') }}"></span></span>
|
||||
</button>
|
||||
{{ user.render_inline(udict[column.raw], badge=false) }}
|
||||
{%- elif column.type == 'record' and column.raw -%}
|
||||
<a href="{{ url('record_detail', rid=column.raw) if canView else '' }}"{% if column.hover %} data-tooltip="{{ column.hover }}"{% endif %}>
|
||||
<span style="font-weight:bold;color:{{ utils.status.getScoreColor(column.score|default(column.value)) }}">{{ column.value|string|nl2br|safe }}</span>
|
||||
</a>
|
||||
{%- elif column.type == 'records' -%}
|
||||
{%- for record in column.raw -%}
|
||||
{%- if loop.index0 -%}/{%- endif -%}
|
||||
{%- if record.raw -%}
|
||||
<a href="{{ url('record_detail', rid=record.raw) if canView else '' }}">
|
||||
{%- set _color = utils.status.getScoreColor(record.score|default(record.value)) -%}
|
||||
<span style="font-weight:bold;color:{{ _color }}">{{ record.value|string|nl2br|safe }}</span>
|
||||
</a>
|
||||
{%- else -%}
|
||||
{{ record.value|string|nl2br|safe }}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- else -%}
|
||||
<span{% if column.hover %} data-tooltip="{{ column.hover }}"{% endif %}>{{ column.value|string|nl2br|safe }}</span>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
{% endmacro %}
|
||||
|
||||
<div data-fragment-id="scoreboard">
|
||||
{% if model.contest.isLocked(tdoc) %}
|
||||
<div class="section__body no-padding">
|
||||
@@ -42,42 +77,16 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- set canViewAll = handler.user.own(tdoc) or model.contest.canShowRecord.call(handler, tdoc) -%}
|
||||
{%- for row in rows -%}{%- if loop.index0 > 0 -%}
|
||||
<tr>
|
||||
{%- for column in row -%}
|
||||
<td class="col--{{ rows[0][loop.index0]['type'] }}"{% if column.style %} style="{{ column.style }}"{% endif %}>
|
||||
{%- if column.type == 'rank' -%}
|
||||
<span class="{{ 'rank--unrank' if column.value == '0' else 'rank--normal' }}">{{ '*' if column.value == '0' else column.value|string|nl2br|safe }}</span>
|
||||
{%- elif column.type == 'user' -%}
|
||||
{%- set canView = canViewAll or handler.user._id == column.raw -%}
|
||||
<button class="star user--{{ column.raw }}" data-uid="{{ column.raw }}">
|
||||
<span class="starred--hide"><span class="icon icon-star--outline" data-tooltip="{{ _('Star') }}"></span></span>
|
||||
<span class="starred--show"><span class="icon icon-star" data-tooltip="{{ _('Unstar') }}"></span></span>
|
||||
</button>
|
||||
{{ user.render_inline(udict[column.raw], badge=false) }}
|
||||
{%- elif column.type == 'record' and column.raw -%}
|
||||
<a href="{{ url('record_detail', rid=column.raw) if canView else '' }}" data-tooltip="{{ column.hover }}">
|
||||
<span style="font-weight:bold;color:{{ utils.status.getScoreColor(column.score|default(column.value)) }}">{{ column.value|string|nl2br|safe }}</span>
|
||||
</a>
|
||||
{%- elif column.type == 'records' -%}
|
||||
{%- for record in column.raw -%}
|
||||
{%- if loop.index0 -%}/{%- endif -%}
|
||||
{%- if record.raw -%}
|
||||
<a href="{{ url('record_detail', rid=record.raw) if canView else '' }}">
|
||||
{%- set _color = utils.status.getScoreColor(record.score|default(record.value)) -%}
|
||||
<span style="font-weight:bold;color:{{ _color }}">{{ record.value|string|nl2br|safe }}</span>
|
||||
</a>
|
||||
{%- else -%}
|
||||
{{ record.value|string|nl2br|safe }}
|
||||
{%- for row in rows -%}
|
||||
{%- if loop.index0 == 1001 -%}
|
||||
{{ noscript_note.render() }}
|
||||
{%- endif -%}
|
||||
{%- if loop.index0 > 1000 -%}
|
||||
<tr style="display:none">{{ scoreboardRow(row) }}</tr>
|
||||
{%- elif loop.index0 > 0 -%}
|
||||
<tr>{{ scoreboardRow(row) }}</tr>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- else -%}
|
||||
<span data-tooltip="{{ column.hover }}">{{ column.value|string|nl2br|safe }}</span>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
{%- endif -%}{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user