| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- 'use strict';
- (function () {
- const ICON_DOWNLOAD = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3v12"/><path d="M7 10l5 5 5-5"/><path d="M4 21h16"/></svg>';
- function esc(value) {
- const div = document.createElement('div');
- div.textContent = String(value ?? '');
- return div.innerHTML;
- }
- const state = {
- initialized: false,
- loading: false,
- root: '',
- items: [],
- filter: 'all',
- keyword: '',
- };
- const FILTER_LABELS = {
- logo: 'LOGO',
- banner: '海报',
- signage: '招牌',
- sticker: '贴纸',
- dish: '菜品',
- other: '其他',
- };
- function formatBytes(size) {
- if (!Number.isFinite(size) || size <= 0) return '—';
- if (size < 1024 * 1024) return `${Math.round(size / 1024)} KB`;
- return `${(size / 1024 / 1024).toFixed(1)} MB`;
- }
- function formatTime(value) {
- if (!value) return '';
- const date = new Date(value);
- const pad = (n) => String(n).padStart(2, '0');
- return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
- }
- function getFilteredItems() {
- const keyword = state.keyword.trim().toLowerCase();
- return state.items.filter((item) => {
- if (state.filter !== 'all' && item.kind !== state.filter) return false;
- if (!keyword) return true;
- return `${item.shopName} ${item.name} ${item.fileName}`.toLowerCase().includes(keyword);
- });
- }
- function renderSummary() {
- const summary = document.getElementById('historySummary');
- const filtered = getFilteredItems();
- if (state.loading) {
- summary.textContent = '正在加载历史作品…';
- return;
- }
- summary.textContent = state.items.length
- ? `共 ${state.items.length} 件作品 · 当前显示 ${filtered.length} 件`
- : '暂无历史作品';
- }
- function renderGallery() {
- const gallery = document.getElementById('historyGallery');
- const items = getFilteredItems();
- gallery.classList.toggle('empty', items.length === 0);
- if (!items.length) {
- gallery.innerHTML = `
- <div class="history-empty">
- <div class="history-empty-icon">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="3"/><circle cx="9" cy="10" r="1.8"/><path d="M21 16l-5-5-6 6"/></svg>
- </div>
- <p>${state.loading ? '正在加载作品' : '暂无匹配的历史作品'}</p>
- <small>${state.loading ? '请稍候' : '生成完成的作品会自动出现在这里'}</small>
- </div>`;
- return;
- }
- gallery.innerHTML = '';
- items.forEach((item) => {
- const card = document.createElement('figure');
- card.className = 'creation-card';
- card.dataset.kind = item.kind;
- const frame = document.createElement('div');
- frame.className = 'creation-frame';
- if (item.kind === 'sticker') frame.classList.add('transparent-bg');
- const image = document.createElement('img');
- image.src = item.url;
- image.alt = `${item.shopName} ${item.name}`;
- image.loading = 'lazy';
- frame.appendChild(image);
- window.shanHoverZoom(frame, image.src, item.kind === 'sticker');
- const kind = document.createElement('span');
- kind.className = 'creation-kind';
- kind.textContent = FILTER_LABELS[item.kind] || '其他';
- frame.appendChild(kind);
- const download = document.createElement('a');
- download.className = 'result-download-icon';
- download.href = item.url;
- download.download = '';
- download.title = '下载原图';
- download.setAttribute('aria-label', '下载原图');
- download.innerHTML = ICON_DOWNLOAD;
- frame.appendChild(download);
- const caption = document.createElement('figcaption');
- const title = document.createElement('div');
- title.className = 'creation-title';
- title.title = item.name;
- title.textContent = item.name;
- const shop = document.createElement('div');
- shop.className = 'creation-shop';
- shop.title = item.shopName;
- shop.textContent = item.shopName;
- const meta = document.createElement('div');
- meta.className = 'creation-meta';
- meta.textContent = `${formatTime(item.modifiedAt)} · ${formatBytes(item.fileSizeBytes)}`;
- caption.append(title, shop, meta);
- card.append(frame, caption);
- gallery.appendChild(card);
- });
- }
- function render() {
- renderSummary();
- renderGallery();
- }
- async function loadHistory() {
- if (state.loading) return;
- state.loading = true;
- render();
- try {
- const rootResponse = await fetch('/api/default-root');
- const rootData = await rootResponse.json();
- state.root = rootData.root;
- const response = await fetch(`/api/creations?root=${encodeURIComponent(state.root)}&limit=600`);
- const data = await response.json();
- if (!response.ok) throw new Error(data.error || '历史作品加载失败');
- state.items = data.items || [];
- } catch (error) {
- state.items = [];
- renderGallery();
- document.getElementById('historySummary').textContent = error.message;
- } finally {
- state.loading = false;
- render();
- }
- }
- function bindEvents() {
- document.getElementById('btnRefreshHistory').addEventListener('click', loadHistory);
- document.getElementById('historySearch').addEventListener('input', (event) => {
- state.keyword = event.target.value;
- render();
- });
- document.getElementById('historyFilters').addEventListener('click', (event) => {
- const button = event.target.closest('[data-filter]');
- if (!button) return;
- state.filter = button.dataset.filter;
- document.querySelectorAll('#historyFilters .history-filter').forEach((item) => {
- item.classList.toggle('active', item === button);
- });
- render();
- });
- }
- window.shanHistoryInit = function () {
- if (!state.initialized) {
- state.initialized = true;
- bindEvents();
- }
- loadHistory();
- };
- })();
|