diff --git a/glossary/GT_bindings.js b/glossary/GT_bindings.js index a14f70d..1258eb0 100644 --- a/glossary/GT_bindings.js +++ b/glossary/GT_bindings.js @@ -4,6 +4,7 @@ import { extensionName } from "../utils/settings.js"; import { safeLorebooks } from '../core/tavernhelper-compatibility.js'; import { testSybdApiConnection, fetchSybdModels } from '../core/api/SybdApi.js'; import { handleFileUpload, processNovel } from './index.js'; +import { reorganizeEntriesByHeadings, loadDatabaseFiles } from './executor.js'; import { SETTINGS_KEY as PRESET_SETTINGS_KEY } from '../PresetSettings/config.js'; const moduleState = { @@ -398,14 +399,70 @@ function bindTabEvents() { if (tabId === 'context') { renderWorldBookEntries(); + } else if (tabId === 'tools') { + const statusEl = document.getElementById('reorganize-status'); + if (statusEl) { + if (moduleState.selectedWorldBook) { + statusEl.textContent = `当前已选择世界书: "${moduleState.selectedWorldBook}"。可以开始重组。`; + statusEl.style.color = ''; + } else { + statusEl.textContent = '请先在“小说处理”标签页中选择一个世界书。'; + statusEl.style.color = '#ffdb58'; // Warning color + } + } } }); }); } +function bindReorganizeEvents() { + const reorganizeBtn = document.getElementById('reorganize-entries-by-heading'); + const statusEl = document.getElementById('reorganize-status'); + const headingsListEl = document.getElementById('reorganize-headings-list'); + + if (!reorganizeBtn || !statusEl || !headingsListEl) return; + + const updateStatusCallback = (message, type = 'info') => { + statusEl.textContent = message; + statusEl.style.color = type === 'error' ? '#ff8a8a' : (type === 'success' ? '#8aff8a' : ''); + }; + + reorganizeBtn.addEventListener('click', async () => { + const headingsToProcess = headingsListEl.value.split('\n').map(h => h.trim()).filter(Boolean); + if (headingsToProcess.length === 0) { + updateStatusCallback('错误:请在文本框中输入至少一个要重组的标题。', 'error'); + return; + } + + const bookName = moduleState.selectedWorldBook; + if (!bookName) { + updateStatusCallback('错误:请先在“小说处理”标签页中选择一个世界书。', 'error'); + return; + } + + const originalHtml = reorganizeBtn.innerHTML; + reorganizeBtn.disabled = true; + reorganizeBtn.innerHTML = ' 正在重组...'; + + try { + await reorganizeEntriesByHeadings(bookName, headingsToProcess, updateStatusCallback); + + if (document.querySelector('.glossary-tab[data-tab="context"].active')) { + renderWorldBookEntries(); + } + } catch (error) { + console.error('An error occurred during reorganization:', error); + } finally { + reorganizeBtn.disabled = false; + reorganizeBtn.innerHTML = originalHtml; + } + }); +} + function bindNovelProcessEvents() { const fileInput = document.getElementById('novel-file-input'); const fileLabel = document.querySelector('label[for="novel-file-input"]'); + const dbSelectBtn = document.getElementById('select-from-database-button'); const processBtn = document.getElementById('novel-confirm-and-process'); const chunkSizeInput = document.getElementById('novel-chunk-size'); const chunkCountEl = document.getElementById('novel-chunk-count'); @@ -511,13 +568,31 @@ function bindNovelProcessEvents() { fileInput.click(); }); fileInput.addEventListener('change', (event) => { - handleFileUpload(event.target.files[0], (content) => { + const file = event.target.files[0]; + if (!file) return; + fileLabel.innerHTML = ` 已选择: ${file.name}`; + handleFileUpload(file, (content) => { fileContent = content; updateChunks(); }); }); } + if (dbSelectBtn) { + dbSelectBtn.addEventListener('click', () => { + loadDatabaseFiles(); + }); + } + + document.addEventListener('novel-file-loaded', (event) => { + const { content, fileName } = event.detail; + fileContent = content; + updateChunks(); + if (fileLabel) { + fileLabel.innerHTML = ` 2a. 上传本地文件 (.txt)`; + } + }); + if (chunkSizeInput) { chunkSizeInput.addEventListener('input', updateChunks); } @@ -530,11 +605,14 @@ function bindNovelProcessEvents() { processBtn.innerHTML = ' 正在中止...'; processBtn.disabled = true; } else { - if (processingState.lastStatus === 'success') { - resetProcessing(); - } - if (processingState.lastStatus === 'idle' || processingState.lastStatus === 'success') { - processingState.currentIndex = 0; + if (processingState.lastStatus !== 'paused') { + const startBatchInput = document.getElementById('novel-start-batch-index'); + let startBatch = parseInt(startBatchInput.value, 10); + if (isNaN(startBatch) || startBatch < 1) { + startBatch = 1; + if (startBatchInput) startBatchInput.value = 1; + } + processingState.currentIndex = (startBatch - 1); } startOrResumeProcessing(); } @@ -585,9 +663,9 @@ export function bindGlossaryEvents() { bindManualActionEvents(); bindTabEvents(); bindNovelProcessEvents(); + bindReorganizeEvents(); loadWorldBooks(); - // 监听角色加载事件,以确保 world_names 可用 eventSource.on(event_types.CHARACTER_PAGE_LOADED, () => { console.log('[Amily2-术语表] 检测到角色加载,重新加载世界书列表以确保同步。'); loadWorldBooks(); @@ -595,8 +673,7 @@ export function bindGlossaryEvents() { const worldBookSelect = document.getElementById('novel-world-book-select'); if (worldBookSelect) { - worldBookSelect.addEventListener('change', () => { - const selectedValue = worldBookSelect.value; + const updateOnBookSelect = (selectedValue) => { updateAndSaveSetting('selectedWorldBook', selectedValue); moduleState.selectedWorldBook = selectedValue; @@ -604,7 +681,29 @@ export function bindGlossaryEvents() { if (contextTab && contextTab.classList.contains('active')) { renderWorldBookEntries(); } + + const toolsTab = document.querySelector('.glossary-tab[data-tab="tools"]'); + if (toolsTab && toolsTab.classList.contains('active')) { + const statusEl = document.getElementById('reorganize-status'); + if (statusEl) { + if (selectedValue) { + statusEl.textContent = `当前已选择世界书: "${selectedValue}"。可以开始重组。`; + statusEl.style.color = ''; + } else { + statusEl.textContent = '请先在“小说处理”标签页中选择一个世界书。'; + statusEl.style.color = '#ffdb58'; + } + } + } + }; + + worldBookSelect.addEventListener('change', () => { + updateOnBookSelect(worldBookSelect.value); }); + + if (moduleState.selectedWorldBook) { + updateOnBookSelect(moduleState.selectedWorldBook); + } } panel.dataset.eventsBound = 'true';