'use strict';
const $ = selector => document.querySelector(selector);
const icon = name => ``;
const state = {route:'推荐', tag:'全部', tab:'全部', query:'', selected:null, saved:new Set(), queue:[]};
const positions = new Map();
let toastTimer, detailOrigin, viewerOrigin, infoOrigin;
let sequence = [];
const headings = {
推荐: ['ARTWORK FEED', '推荐作品', '浏览作品,选择后查看详情。'],
发现: ['CATEGORIES', '分类浏览', '按示例分类筛选作品。'],
动态: ['FOLLOWING', '关注动态', '动态列表布局示例,使用本地作品数据。'],
收藏: ['SAVED ARTWORKS', '我的收藏', '仅显示本次预览中收藏的作品。'],
};
function toast(message) {
$('#toast').textContent = message;
$('#toast').classList.add('visible');
clearTimeout(toastTimer);
toastTimer = setTimeout(() => $('#toast').classList.remove('visible'), 2600);
}
function filtered() {
let items = artworks.filter(a => (state.tag === '全部' || a.tag === state.tag)
&& (!state.query || `${a.title} ${a.tag} ${a.id}`.includes(state.query))
&& (state.route !== '收藏' || state.saved.has(a.id)));
if (state.tab === '热门' || state.route === '动态') items = [...items].reverse();
return items;
}
function anchor() {
if (!$('#feed').getClientRects().length) return null;
const top = $('#feed').getBoundingClientRect().top;
const card = [...document.querySelectorAll('.card')].find(v => v.getBoundingClientRect().bottom > top);
return card ? {id:card.dataset.id, offset:card.getBoundingClientRect().top - top} : null;
}
function restoreAnchor(position) {
if (!position || !$('#feed').getClientRects().length) return;
const card = document.querySelector(`.card[data-id="${position.id}"]`);
if (card) $('#feed').scrollTop += card.getBoundingClientRect().top - $('#feed').getBoundingClientRect().top - position.offset;
}
function render() {
const items = filtered();
const unavailable = TabletPreview.status($('#preview-state'));
$('#count').textContent = `${items.length} 幅作品 · 示例`;
$('#gallery').hidden = unavailable;
$('#empty').hidden = unavailable || items.length > 0;
$('#empty h2').textContent = state.route === '收藏' && !state.saved.size ? '暂无收藏' : '暂无匹配作品';
$('#empty p').textContent = state.route === '收藏' && !state.saved.size ? '可在作品卡片或详情中收藏作品。' : '请调整关键词或分类。';
$('#gallery').innerHTML = items.map(a => `
画廊布局与交互示例,未连接账号或业务接口。
/ 搜索 · Esc 返回 · ← → 全屏切图
${TabletPreview.controls()}`); } function route(value) { const position = anchor(); if (position) positions.set(state.route, position); closeDetail(false); state.route = value; document.querySelectorAll('[data-route]').forEach(button => { const active = button.dataset.route === value; button.classList.toggle('active', active); if (active) button.setAttribute('aria-current', 'page'); else button.removeAttribute('aria-current'); }); const [eyebrow,title,description] = headings[value]; $('#eyebrow').textContent = eyebrow; $('#page-title').textContent = title; $('#subtitle').textContent = description; state.query = ''; state.tag = '全部'; state.tab = '全部'; $('#search').value = ''; render(); $('#feed').scrollTop = 0; restoreAnchor(positions.get(value)); } document.addEventListener('click', event => { const open = event.target.closest('[data-open]'); if (open) openDetail(open.dataset.open); const save = event.target.closest('[data-like]'); if (save) like(save.dataset.like); }); document.querySelectorAll('[data-route]').forEach(button => button.onclick = () => route(button.dataset.route)); document.querySelectorAll('[data-tag],[data-tab]').forEach(button => button.onclick = () => { if (button.dataset.tag) state.tag = button.dataset.tag; else state.tab = button.dataset.tab; render(); if (button.dataset.tab === '热门') toast('热门排序为示例'); }); $('#search').oninput = event => { state.query = event.target.value.trim(); render(); }; $('#clear-filters').onclick = () => route('推荐'); $('#density').onchange = event => { const position = anchor(); document.documentElement.style.setProperty('--card', {normal:'198px', compact:'152px', large:'260px'}[event.target.value]); $('#gallery').classList.toggle('large', event.target.value === 'large'); restoreAnchor(position); }; $('#theme').onclick = TabletPreview.toggleTheme; $('#preview-settings').onclick = settings; $('#account').onclick = settings; $('#downloads').onclick = () => info(`${state.queue.length ? state.queue.map(id => `作品 ${id} · 已加入模拟队列`).join('
') : '暂无下载任务。可在作品详情中添加模拟下载。'}
此处仅演示队列,不下载文件。
`); $('#close-info').onclick = () => $('#info').close(); $('#info').addEventListener('close', () => infoOrigin?.focus({preventScroll:true})); $('#exit-viewer').onclick = () => $('#viewer').close(); $('#viewer').addEventListener('close', () => (document.getElementById(viewerOrigin) || $('#close-detail'))?.focus({preventScroll:true})); $('#prev').onclick = () => stepViewer(-1); $('#next').onclick = () => stepViewer(1); $('#zoom').onclick = () => { const zoomed = $('.viewer-canvas').classList.toggle('zoomed'); $('#zoom').textContent = zoomed ? '适应窗口' : '放大'; $('#zoom').setAttribute('aria-pressed', zoomed); }; document.addEventListener('previewstate', () => { closeDetail(false); render(); }); document.addEventListener('keydown', event => { if (event.target.matches('input,select,textarea')) return; const viewing = $('#viewer').open, informing = $('#info').open; if (event.key === '/' && !viewing && !informing) { event.preventDefault(); $('#search').focus(); } if (event.key === 'Escape' && !viewing && !informing && state.selected) { event.preventDefault(); closeDetail(); } if (viewing && ['ArrowLeft','ArrowRight'].includes(event.key)) { event.preventDefault(); stepViewer(event.key === 'ArrowLeft' ? -1 : 1); } }); render();