/** * @file js/ui/glossary-editor-enhanced.js * @description 增强版术语库编辑器 - 支持大数据量、搜索、分页、批量操作 */ (function() { const ITEMS_PER_PAGE = 20; // 每页显示条数 // 编辑器状态 const editorState = { currentSetId: null, allEntries: [], filteredEntries: [], currentPage: 1, totalPages: 0, searchQuery: '', selectedIds: new Set(), selectAll: false }; /** * 打开增强版编辑器 * @param {string} setId - 术语库 ID */ async function openEnhancedEditor(setId) { if (!setId) return; editorState.currentSetId = setId; editorState.currentPage = 1; editorState.searchQuery = ''; editorState.selectedIds.clear(); editorState.selectAll = false; // 显示加载提示 showEditorLoading(); try { // 从缓存加载数据 const sets = window._glossarySetsCache || {}; const set = sets[setId]; if (!set) { throw new Error('术语库不存在'); } editorState.allEntries = Array.isArray(set.entries) ? set.entries : []; editorState.filteredEntries = [...editorState.allEntries]; editorState.totalPages = Math.ceil(editorState.filteredEntries.length / ITEMS_PER_PAGE); // 渲染编辑器 renderEnhancedEditor(set); } catch (err) { console.error('Failed to open enhanced editor:', err); alert('打开术语库失败: ' + err.message); } } /** * 显示加载提示 */ function showEditorLoading() { const container = document.getElementById('glossaryEntriesTable'); if (!container) return; container.innerHTML = `

正在加载术语库数据...

`; } /** * 渲染增强版编辑器 * @param {Object} set - 术语库对象 */ function renderEnhancedEditor(set) { const panel = document.getElementById('glossaryEditorPanel'); if (!panel) return; panel.dataset.editingId = set.id; panel.classList.remove('hidden'); // 渲染顶部工具栏 renderToolbar(set); // 渲染条目列表 renderEntriesList(); // 渲染分页控件 renderPagination(); } /** * 渲染工具栏 * @param {Object} set - 术语库对象 */ function renderToolbar(set) { const toolbarContainer = document.getElementById('glossaryEditorToolbar'); if (!toolbarContainer) return; const totalEntries = editorState.allEntries.length; const filteredCount = editorState.filteredEntries.length; const selectedCount = editorState.selectedIds.size; toolbarContainer.innerHTML = `

${escapeHtml(set.name)}

共 ${totalEntries.toLocaleString()} 条 ${filteredCount !== totalEntries ? `,筛选后 ${filteredCount.toLocaleString()} 条` : ''} ${selectedCount > 0 ? `,已选择 ${selectedCount} 条` : ''}

|
${editorState.searchQuery ? ` ` : ''}
${selectedCount > 0 ? `
已选择 ${selectedCount} 条
` : ''}
`; } /** * 渲染条目列表(分页) */ function renderEntriesList() { const container = document.getElementById('glossaryEntriesTable'); if (!container) return; const start = (editorState.currentPage - 1) * ITEMS_PER_PAGE; const end = Math.min(start + ITEMS_PER_PAGE, editorState.filteredEntries.length); const pageEntries = editorState.filteredEntries.slice(start, end); if (pageEntries.length === 0) { container.innerHTML = `

${editorState.searchQuery ? '未找到匹配的术语' : '暂无术语条目'}

`; return; } const rows = pageEntries.map((entry, index) => { const globalIndex = start + index; const isSelected = editorState.selectedIds.has(entry.id); return ` ${globalIndex + 1} `; }).join(''); container.innerHTML = `
${rows}
# 术语 译文 区分大小写 全词匹配 启用 操作
显示 ${start + 1} - ${end} 条,共 ${editorState.filteredEntries.length.toLocaleString()} 条
`; } /** * 渲染分页控件 */ function renderPagination() { const container = document.getElementById('glossaryEditorPagination'); if (!container) return; if (editorState.totalPages <= 1) { container.innerHTML = ''; return; } const currentPage = editorState.currentPage; const totalPages = editorState.totalPages; // 生成页码按钮 const pageButtons = []; const maxVisible = 7; if (totalPages <= maxVisible) { // 显示所有页码 for (let i = 1; i <= totalPages; i++) { pageButtons.push(i); } } else { // 智能显示页码 if (currentPage <= 4) { pageButtons.push(1, 2, 3, 4, 5, '...', totalPages); } else if (currentPage >= totalPages - 3) { pageButtons.push(1, '...', totalPages - 4, totalPages - 3, totalPages - 2, totalPages - 1, totalPages); } else { pageButtons.push(1, '...', currentPage - 1, currentPage, currentPage + 1, '...', totalPages); } } const buttonsHTML = pageButtons.map(page => { if (page === '...') { return '...'; } const isActive = page === currentPage; return ` `; }).join(''); container.innerHTML = `
${buttonsHTML}
`; } /** * 处理搜索 * @param {string} query - 搜索关键词 */ function handleSearch(query) { editorState.searchQuery = query.trim(); editorState.currentPage = 1; if (!editorState.searchQuery) { editorState.filteredEntries = [...editorState.allEntries]; } else { const lowerQuery = editorState.searchQuery.toLowerCase(); editorState.filteredEntries = editorState.allEntries.filter(entry => { return entry.term.toLowerCase().includes(lowerQuery) || entry.translation.toLowerCase().includes(lowerQuery); }); } editorState.totalPages = Math.ceil(editorState.filteredEntries.length / ITEMS_PER_PAGE); // 重新渲染 const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (set) { renderToolbar(set); renderEntriesList(); renderPagination(); } } /** * 清除搜索 */ function clearSearch() { document.getElementById('glossarySearchInput').value = ''; handleSearch(''); } /** * 跳转到指定页 * @param {number} page - 页码 */ function goToPage(page) { if (page < 1 || page > editorState.totalPages) return; editorState.currentPage = page; renderEntriesList(); renderPagination(); // 滚动到顶部 const container = document.getElementById('glossaryEntriesTable'); if (container) { container.scrollIntoView({ behavior: 'smooth', block: 'start' }); } } /** * 切换选择 * @param {string} entryId - 条目 ID */ function toggleSelection(entryId) { if (editorState.selectedIds.has(entryId)) { editorState.selectedIds.delete(entryId); } else { editorState.selectedIds.add(entryId); } // 更新全选状态 editorState.selectAll = editorState.selectedIds.size === editorState.filteredEntries.length; // 重新渲染 const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (set) { renderToolbar(set); renderEntriesList(); } } /** * 全选/取消全选 * @param {boolean} checked - 是否选中 */ function toggleSelectAll(checked) { editorState.selectAll = checked; if (checked) { editorState.filteredEntries.forEach(entry => { editorState.selectedIds.add(entry.id); }); } else { editorState.selectedIds.clear(); } // 重新渲染 const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (set) { renderToolbar(set); renderEntriesList(); } } /** * 清除选择 */ function clearSelection() { editorState.selectedIds.clear(); editorState.selectAll = false; // 重新渲染 const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (set) { renderToolbar(set); renderEntriesList(); } } /** * 更新条目 * @param {string} entryId - 条目 ID * @param {string} field - 字段名 * @param {any} value - 新值 */ function updateEntry(entryId, field, value) { const entry = editorState.allEntries.find(e => e.id === entryId); if (!entry) return; entry[field] = value; // 保存到缓存和 IndexedDB saveCurrentSet(); } /** * 删除条目 * @param {string} entryId - 条目 ID */ function deleteEntry(entryId) { if (!confirm('确认删除该条目?')) return; editorState.allEntries = editorState.allEntries.filter(e => e.id !== entryId); editorState.filteredEntries = editorState.filteredEntries.filter(e => e.id !== entryId); editorState.selectedIds.delete(entryId); editorState.totalPages = Math.ceil(editorState.filteredEntries.length / ITEMS_PER_PAGE); // 调整当前页 if (editorState.currentPage > editorState.totalPages && editorState.totalPages > 0) { editorState.currentPage = editorState.totalPages; } // 保存并重新渲染 saveCurrentSet(); const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (set) { renderToolbar(set); renderEntriesList(); renderPagination(); } } /** * 批量启用/禁用 * @param {boolean} enabled - 是否启用 */ function bulkEnable(enabled) { let count = 0; editorState.selectedIds.forEach(entryId => { const entry = editorState.allEntries.find(e => e.id === entryId); if (entry) { entry.enabled = enabled; count++; } }); if (count > 0) { saveCurrentSet(); renderEntriesList(); alert(`已${enabled ? '启用' : '禁用'} ${count} 条术语`); } } /** * 批量删除 */ function bulkDelete() { const count = editorState.selectedIds.size; if (count === 0) return; if (!confirm(`确认删除选中的 ${count} 条术语?此操作不可撤销。`)) return; editorState.allEntries = editorState.allEntries.filter(e => !editorState.selectedIds.has(e.id)); editorState.filteredEntries = editorState.filteredEntries.filter(e => !editorState.selectedIds.has(e.id)); editorState.selectedIds.clear(); editorState.selectAll = false; editorState.totalPages = Math.ceil(editorState.filteredEntries.length / ITEMS_PER_PAGE); // 调整当前页 if (editorState.currentPage > editorState.totalPages && editorState.totalPages > 0) { editorState.currentPage = editorState.totalPages; } // 保存并重新渲染 saveCurrentSet(); const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (set) { renderToolbar(set); renderEntriesList(); renderPagination(); } alert(`已删除 ${count} 条术语`); } /** * 新增条目 */ function addNewEntry() { const newEntry = { id: generateUUID(), term: '', translation: '', caseSensitive: false, wholeWord: false, enabled: true }; editorState.allEntries.unshift(newEntry); // 添加到开头 editorState.filteredEntries.unshift(newEntry); editorState.totalPages = Math.ceil(editorState.filteredEntries.length / ITEMS_PER_PAGE); editorState.currentPage = 1; // 跳转到第一页 // 保存并重新渲染 saveCurrentSet(); const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (set) { renderToolbar(set); renderEntriesList(); renderPagination(); } } /** * 打开导入功能(复用旧版的导入模态框) */ function openImport() { if (typeof openGlossaryImportModal === 'function') { openGlossaryImportModal(editorState.currentSetId); } else { alert('导入功能暂不可用'); } } /** * 打开导出功能(复用旧版的导出模态框) */ function openExport() { if (typeof openGlossaryExportModal === 'function') { openGlossaryExportModal(editorState.currentSetId); } else { alert('导出功能暂不可用'); } } /** * 切换智能过滤开关 * @param {boolean} enabled - 是否启用智能过滤 */ function toggleSmartFilter(enabled) { if (!editorState.currentSetId) return; const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (!set) return; // 更新配置 set.enableSmartFilter = enabled; // 保存到存储(使用同步函数,会自动触发异步保存) if (typeof renameGlossarySet === 'function') { // 触发保存(名称不变,只更新元数据) renameGlossarySet(editorState.currentSetId, set.name); } // 重新渲染工具栏以显示新状态 renderToolbar(set); // 提示用户 const message = enabled ? '已启用智能过滤:翻译时自动过滤通用词汇,只保留专业术语' : '已禁用智能过滤:翻译时使用所有匹配的术语'; if (typeof showNotification === 'function') { showNotification(message, 'success'); } else { console.log(message); } } /** * 更新术语数量限制 * @param {number} maxTerms - 最大术语数量 */ function updateMaxTerms(maxTerms) { if (!editorState.currentSetId) return; const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (!set) return; // 验证数值范围 if (isNaN(maxTerms) || maxTerms < 1) { maxTerms = 1; } else if (maxTerms > 500) { maxTerms = 500; } // 更新配置 set.maxTermsInPrompt = maxTerms; // 保存到存储 if (typeof renameGlossarySet === 'function') { renameGlossarySet(editorState.currentSetId, set.name); } // 重新渲染工具栏 renderToolbar(set); // 提示用户 const message = `已设置术语数量限制为 ${maxTerms} 条`; if (typeof showNotification === 'function') { showNotification(message, 'success'); } else { console.log(message); } } /** * 保存当前术语库 */ function saveCurrentSet() { if (!editorState.currentSetId) return; const sets = window._glossarySetsCache || {}; const set = sets[editorState.currentSetId]; if (!set) return; // 更新条目 set.entries = editorState.allEntries; // 保存(使用 storage.js 的函数) if (typeof updateGlossarySetEntries === 'function') { updateGlossarySetEntries(editorState.currentSetId, editorState.allEntries); } } /** * 关闭编辑器 */ function closeEditor() { const panel = document.getElementById('glossaryEditorPanel'); if (panel) { panel.classList.add('hidden'); panel.dataset.editingId = ''; } // 清空状态 editorState.currentSetId = null; editorState.allEntries = []; editorState.filteredEntries = []; editorState.selectedIds.clear(); editorState.selectAll = false; } /** * HTML 转义 */ function escapeHtml(str) { return String(str || '').replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } // 暴露到全局 window.glossaryEditorEnhanced = { open: openEnhancedEditor, close: closeEditor, handleSearch, clearSearch, goToPage, toggleSelection, toggleSelectAll, clearSelection, updateEntry, deleteEntry, bulkEnable, bulkDelete, addNewEntry, openImport, openExport, toggleSmartFilter, updateMaxTerms }; console.log('[GlossaryEditorEnhanced] Enhanced editor loaded'); })();