Update WorldEditor.js

This commit is contained in:
2025-10-23 22:17:27 +08:00
committed by GitHub
parent ae5e3e685e
commit 66703928cf

View File

@@ -2,21 +2,18 @@
import { world_names, loadWorldInfo, saveWorldInfo, deleteWorldInfo, updateWorldInfoList } from "/scripts/world-info.js"; import { world_names, loadWorldInfo, saveWorldInfo, deleteWorldInfo, updateWorldInfoList } from "/scripts/world-info.js";
import { eventSource, event_types } from '/script.js'; import { eventSource, event_types } from '/script.js';
import { showHtmlModal } from '/scripts/extensions/third-party/ST-Amily2-Chat-Optimisation/ui/page-window.js'; import { showHtmlModal } from '/scripts/extensions/third-party/ST-Amily2-Chat-Optimisation/ui/page-window.js';
import { safeLorebooks, safeLorebookEntries, safeUpdateLorebookEntries } from '../core/tavernhelper-compatibility.js'; import { safeLorebooks, safeLorebookEntries, safeUpdateLorebookEntries, compatibleWriteToLorebook } from '../core/tavernhelper-compatibility.js';
import { writeToLorebookWithTavernHelper } from '../core/lore.js'; import { amilyHelper } from '../core/tavern-helper/main.js';
const { SillyTavern, TavernHelper } = window; const { SillyTavern } = window;
class WorldEditor { class WorldEditor {
constructor() { constructor() {
// 通用状态
this.isLoading = false; this.isLoading = false;
// 世界书视图状态
this.allWorldBooks = []; this.allWorldBooks = [];
this.filteredWorldBooks = []; this.filteredWorldBooks = [];
this.selectedWorldBooks = new Set(); this.selectedWorldBooks = new Set();
// 条目视图状态
this.currentWorldBook = null; this.currentWorldBook = null;
this.entries = []; this.entries = [];
this.selectedEntries = new Set(); this.selectedEntries = new Set();
@@ -204,7 +201,7 @@ class WorldEditor {
if (bookName && bookName.trim()) { if (bookName && bookName.trim()) {
const trimmedBookName = bookName.trim(); const trimmedBookName = bookName.trim();
try { try {
await writeToLorebookWithTavernHelper(trimmedBookName, '新条目', () => '这是一个新条目', {}); await compatibleWriteToLorebook(trimmedBookName, '新条目', () => '这是一个新条目', {});
if (window.toastr) window.toastr.success(`世界书 "${trimmedBookName}" 创建成功!`); if (window.toastr) window.toastr.success(`世界书 "${trimmedBookName}" 创建成功!`);
this.loadAvailableWorldBooks(); this.loadAvailableWorldBooks();
} catch (error) { } catch (error) {
@@ -305,7 +302,7 @@ class WorldEditor {
this.entries = (rawEntries || []).map(e => ({ this.entries = (rawEntries || []).map(e => ({
uid: e.uid, enabled: e.enabled, type: e.type || (e.constant ? 'constant' : 'selective'), uid: e.uid, enabled: e.enabled, type: e.type || (e.constant ? 'constant' : 'selective'),
keys: e.keys || [], content: e.content || '', position: e.position || 'before_character_definition', keys: e.keys || [], content: e.content || '', position: e.position || 'before_character_definition',
depth: (e.position?.startsWith('at_depth')) ? e.depth : null, order: e.order || 100, comment: e.comment || '', depth: (String(e.position)?.startsWith('at_depth')) ? e.depth : null, order: e.order || 100, comment: e.comment || '',
exclude_recursion: e.exclude_recursion, prevent_recursion: e.prevent_recursion exclude_recursion: e.exclude_recursion, prevent_recursion: e.prevent_recursion
})); }));
this.filteredEntries = [...this.entries]; this.filteredEntries = [...this.entries];
@@ -381,7 +378,7 @@ class WorldEditor {
<div data-label="条目"><input type="text" class="inline-edit" data-field="comment" data-uid="${entry.uid}" value="${entry.comment || ''}" placeholder="点击填写条目名"></div> <div data-label="条目"><input type="text" class="inline-edit" data-field="comment" data-uid="${entry.uid}" value="${entry.comment || ''}" placeholder="点击填写条目名"></div>
<div data-label="内容" class="world-editor-entry-content" data-action="open-editor" data-uid="${entry.uid}" title="${entry.content || ''}">${entry.content || ''}</div> <div data-label="内容" class="world-editor-entry-content" data-action="open-editor" data-uid="${entry.uid}" title="${entry.content || ''}">${entry.content || ''}</div>
<div data-label="位置">${positionSelect}</div> <div data-label="位置">${positionSelect}</div>
<div data-label="深度"><input type="number" class="inline-edit" data-field="depth" data-uid="${entry.uid}" value="${entry.depth != null ? entry.depth : ''}" ${!entry.position?.startsWith('at_depth') ? 'disabled' : ''}></div> <div data-label="深度"><input type="number" class="inline-edit" data-field="depth" data-uid="${entry.uid}" value="${entry.depth != null ? entry.depth : ''}" ${!String(entry.position)?.startsWith('at_depth') ? 'disabled' : ''}></div>
<div data-label="顺序"><input type="number" class="inline-edit" data-field="order" data-uid="${entry.uid}" value="${entry.order}"></div> <div data-label="顺序"><input type="number" class="inline-edit" data-field="order" data-uid="${entry.uid}" value="${entry.order}"></div>
</div>`; </div>`;
} }
@@ -523,7 +520,12 @@ class WorldEditor {
async batchDeleteEntries() { async batchDeleteEntries() {
if (this.selectedEntries.size === 0 || !confirm(`删除 ${this.selectedEntries.size} 个条目?`)) return; if (this.selectedEntries.size === 0 || !confirm(`删除 ${this.selectedEntries.size} 个条目?`)) return;
try { try {
await TavernHelper.deleteLorebookEntries(this.currentWorldBook, Array.from(this.selectedEntries)); const bookData = await loadWorldInfo(this.currentWorldBook);
if (!bookData) throw new Error(`World book "${this.currentWorldBook}" not found.`);
this.selectedEntries.forEach(uid => {
delete bookData.entries[uid];
});
await saveWorldInfo(this.currentWorldBook, bookData, true);
this.loadWorldBookEntries(this.currentWorldBook); this.loadWorldBookEntries(this.currentWorldBook);
} catch (error) { } catch (error) {
this.showError(`删除失败: ${error.message}`); this.showError(`删除失败: ${error.message}`);
@@ -605,7 +607,7 @@ class WorldEditor {
await this.updateEntriesWithNativeMethod([{ ...this.currentEditingEntry, ...formData }]); await this.updateEntriesWithNativeMethod([{ ...this.currentEditingEntry, ...formData }]);
} else { } else {
// 创建条目仍然可以使用TavernHelper因为它通常不会触发跳转 // 创建条目仍然可以使用TavernHelper因为它通常不会触发跳转
await TavernHelper.createLorebookEntries(this.currentWorldBook, [formData]); await amilyHelper.createLorebookEntries(this.currentWorldBook, [formData]);
} }
// 刷新当前视图 // 刷新当前视图
this.loadWorldBookEntries(this.currentWorldBook); this.loadWorldBookEntries(this.currentWorldBook);
@@ -667,21 +669,40 @@ class WorldEditor {
} }
function initializeWorldEditor() { function initializeWorldEditor() {
// 确保面板存在 const panel = document.getElementById('amily2_world_editor_panel');
if (!document.getElementById('amily2_world_editor_panel')) { if (!panel) {
console.error('[WorldEditor] Panel not found, initialization aborted.'); console.error('[WorldEditor] Panel not found, initialization aborted.');
return; return;
} }
// 防止重复初始化 if (panel.dataset.initialized) {
if (!window.worldEditorInstance) { return;
console.log('[WorldEditor] Initializing WorldEditor instance.'); }
window.worldEditorInstance = new WorldEditor(); panel.dataset.initialized = 'true';
console.log('[WorldEditor] Initializing WorldEditor instance.');
window.worldEditorInstance = new WorldEditor();
}
function tryInitialize() {
const panel = document.getElementById('amily2_world_editor_panel');
if (panel) {
initializeWorldEditor();
} else {
const observer = new MutationObserver((mutations, obs) => {
const panel = document.getElementById('amily2_world_editor_panel');
if (panel) {
obs.disconnect();
initializeWorldEditor();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
} }
} }
// 确保在DOM加载完毕后执行
if (document.readyState === 'loading') { if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeWorldEditor); document.addEventListener('DOMContentLoaded', tryInitialize);
} else { } else {
initializeWorldEditor(); tryInitialize();
} }