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