mirror of
https://github.com/SilenceLurker/ST-Amily2-Chat-Optimisation.git
synced 2026-06-06 14:45:51 +00:00
Merge branch 'Wx-2025:main' into main
This commit is contained in:
@@ -12,6 +12,7 @@ import { createDrawer } from '../ui/drawer.js';
|
||||
import { messageFormatting } from '/script.js';
|
||||
import { executeManualCommand } from '../core/autoHideManager.js';
|
||||
import { showContentModal, showHtmlModal } from './page-window.js';
|
||||
import { openAutoCharCardWindow } from '../core/auto-char-card/ui-bindings.js';
|
||||
|
||||
function displayDailyAuthCode() {
|
||||
const displayEl = document.getElementById('amily2_daily_code_display');
|
||||
@@ -22,7 +23,7 @@ function displayDailyAuthCode() {
|
||||
displayEl.textContent = todayCode;
|
||||
|
||||
if(copyBtn) copyBtn.style.display = 'inline-block';
|
||||
|
||||
|
||||
copyBtn.onclick = () => {
|
||||
navigator.clipboard.writeText(todayCode).then(() => {
|
||||
toastr.success('授权码已复制到剪贴板!');
|
||||
@@ -722,10 +723,10 @@ export function bindModalEvents() {
|
||||
}
|
||||
);
|
||||
|
||||
container
|
||||
.off("click.amily2.chamber_nav")
|
||||
.on("click.amily2.chamber_nav",
|
||||
"#amily2_open_plot_optimization, #amily2_open_additional_features, #amily2_open_rag_palace, #amily2_open_memorisation_forms, #amily2_open_character_world_book, #amily2_open_world_editor, #amily2_open_glossary, #amily2_open_renderer, #amily2_open_super_memory, #amily2_back_to_main_settings, #amily2_back_to_main_from_hanlinyuan, #amily2_back_to_main_from_forms, #amily2_back_to_main_from_optimization, #amily2_back_to_main_from_cwb, #amily2_back_to_main_from_world_editor, #amily2_back_to_main_from_glossary, #amily2_renderer_back_button, #amily2_back_to_main_from_super_memory", function () {
|
||||
container
|
||||
.off("click.amily2.chamber_nav")
|
||||
.on("click.amily2.chamber_nav",
|
||||
"#amily2_open_text_optimization, #amily2_open_plot_optimization, #amily2_open_additional_features, #amily2_open_rag_palace, #amily2_open_memorisation_forms, #amily2_open_character_world_book, #amily2_open_world_editor, #amily2_open_glossary, #amily2_open_renderer, #amily2_open_super_memory, #amily2_open_auto_char_card, #amily2_back_to_main_settings, #amily2_back_to_main_from_hanlinyuan, #amily2_back_to_main_from_forms, #amily2_back_to_main_from_optimization, #amily2_back_to_main_from_text_optimization, #amily2_back_to_main_from_cwb, #amily2_back_to_main_from_world_editor, #amily2_back_to_main_from_glossary, #amily2_renderer_back_button, #amily2_back_to_main_from_super_memory", function () {
|
||||
if (!pluginAuthStatus.authorized) return;
|
||||
|
||||
const mainPanel = container.find('.plugin-features');
|
||||
@@ -733,6 +734,7 @@ container
|
||||
const hanlinyuanPanel = container.find('#amily2_hanlinyuan_panel');
|
||||
const memorisationFormsPanel = container.find('#amily2_memorisation_forms_panel');
|
||||
const plotOptimizationPanel = container.find('#amily2_plot_optimization_panel');
|
||||
const textOptimizationPanel = container.find('#amily2_text_optimization_panel');
|
||||
const characterWorldBookPanel = container.find('#amily2_character_world_book_panel');
|
||||
const worldEditorPanel = container.find('#amily2_world_editor_panel');
|
||||
const glossaryPanel = container.find('#amily2_glossary_panel');
|
||||
@@ -744,6 +746,7 @@ container
|
||||
hanlinyuanPanel.hide();
|
||||
memorisationFormsPanel.hide();
|
||||
plotOptimizationPanel.hide();
|
||||
textOptimizationPanel.hide();
|
||||
characterWorldBookPanel.hide();
|
||||
worldEditorPanel.hide();
|
||||
glossaryPanel.hide();
|
||||
@@ -751,6 +754,9 @@ container
|
||||
superMemoryPanel.hide();
|
||||
|
||||
switch (this.id) {
|
||||
case 'amily2_open_text_optimization':
|
||||
textOptimizationPanel.show();
|
||||
break;
|
||||
case 'amily2_open_super_memory':
|
||||
const userType = parseInt(localStorage.getItem("plugin_user_type") || "0");
|
||||
if (userType < 2) {
|
||||
@@ -760,6 +766,12 @@ container
|
||||
}
|
||||
superMemoryPanel.show();
|
||||
break;
|
||||
case 'amily2_open_auto_char_card':
|
||||
openAutoCharCardWindow();
|
||||
// 自动构建器是独立窗口,不需要隐藏主面板,或者根据需求决定
|
||||
// 这里我们保持主面板显示,因为它是全屏覆盖的
|
||||
mainPanel.show();
|
||||
return;
|
||||
case 'amily2_open_renderer':
|
||||
rendererPanel.show();
|
||||
break;
|
||||
@@ -788,6 +800,7 @@ container
|
||||
case 'amily2_back_to_main_from_hanlinyuan':
|
||||
case 'amily2_back_to_main_from_forms':
|
||||
case 'amily2_back_to_main_from_optimization':
|
||||
case 'amily2_back_to_main_from_text_optimization':
|
||||
case 'amily2_back_to_main_from_cwb':
|
||||
case 'amily2_back_to_main_from_world_editor':
|
||||
case 'amily2_back_to_main_from_glossary':
|
||||
@@ -1263,6 +1276,7 @@ async function opt_loadTavernApiProfiles(panel) {
|
||||
const opt_characterSpecificSettings = [
|
||||
'plotOpt_worldbookSource',
|
||||
'plotOpt_selectedWorldbooks',
|
||||
'plotOpt_autoSelectWorldbooks',
|
||||
'plotOpt_enabledWorldbookEntries'
|
||||
];
|
||||
|
||||
@@ -1357,10 +1371,21 @@ async function opt_loadWorldbooks(panel) {
|
||||
lorebooks.forEach(name => {
|
||||
const bookId = `amily2-opt-wb-check-${name.replace(/[^a-zA-Z0-9]/g, '-')}`;
|
||||
const isChecked = currentSelection.includes(name);
|
||||
|
||||
// Auto Select Logic
|
||||
const autoId = `amily2-opt-wb-auto-${name.replace(/[^a-zA-Z0-9]/g, '-')}`;
|
||||
const isAuto = (settings.plotOpt_autoSelectWorldbooks || []).includes(name);
|
||||
|
||||
const item = $(`
|
||||
<div class="amily2_opt_worldbook_list_item" style="display: flex; align-items: center;">
|
||||
<input type="checkbox" id="${bookId}" value="${name}" ${isChecked ? 'checked' : ''} style="margin-right: 5px;">
|
||||
<label for="${bookId}" style="margin-bottom: 0;">${name}</label>
|
||||
<div class="amily2_opt_worldbook_list_item" style="display: flex; align-items: center; justify-content: space-between; padding-right: 5px;">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<input type="checkbox" id="${bookId}" value="${name}" ${isChecked ? 'checked' : ''} style="margin-right: 5px;">
|
||||
<label for="${bookId}" style="margin-bottom: 0;">${name}</label>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center;" title="开启后自动加载该世界书所有条目(包括新增)">
|
||||
<input type="checkbox" class="amily2_opt_wb_auto_check" id="${autoId}" data-book="${name}" ${isAuto ? 'checked' : ''} style="margin-right: 5px;">
|
||||
<label for="${autoId}" style="margin-bottom: 0; font-size: 0.9em; opacity: 0.8; cursor: pointer;">全选</label>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
container.append(item);
|
||||
@@ -1463,12 +1488,16 @@ async function opt_loadWorldbookEntries(panel) {
|
||||
|
||||
enabledOnlyEntries.sort((a, b) => (a.comment || '').localeCompare(b.comment || '')).forEach(entry => {
|
||||
const entryId = `amily2-opt-entry-${entry.bookName.replace(/[^a-zA-Z0-9]/g, '-')}-${entry.uid}`;
|
||||
const isEnabled = enabledEntries[entry.bookName]?.includes(entry.uid) ?? true;
|
||||
|
||||
const isAuto = (settings.plotOpt_autoSelectWorldbooks || []).includes(entry.bookName);
|
||||
// If auto is enabled, the entry is forced enabled in logic, so show checked and disabled
|
||||
const isChecked = isAuto || (enabledEntries[entry.bookName]?.includes(entry.uid) ?? true);
|
||||
const isDisabled = isAuto;
|
||||
|
||||
const item = $(`
|
||||
<div class="amily2_opt_worldbook_entry_item" style="display: flex; align-items: center;">
|
||||
<input type="checkbox" id="${entryId}" data-book="${entry.bookName}" data-uid="${entry.uid}" ${isEnabled ? 'checked' : ''} style="margin-right: 5px;">
|
||||
<label for="${entryId}" title="世界书: ${entry.bookName}\nUID: ${entry.uid}" style="margin-bottom: 0;">${entry.comment || '无标题条目'}</label>
|
||||
<input type="checkbox" id="${entryId}" data-book="${entry.bookName}" data-uid="${entry.uid}" ${isChecked ? 'checked' : ''} ${isDisabled ? 'disabled' : ''} style="margin-right: 5px;">
|
||||
<label for="${entryId}" title="世界书: ${entry.bookName}\nUID: ${entry.uid}" style="margin-bottom: 0; ${isDisabled ? 'opacity:0.7;' : ''}">${entry.comment || '无标题条目'} ${isAuto ? '<span style="font-size:0.8em; opacity:0.6;">(全选生效中)</span>' : ''}</label>
|
||||
</div>
|
||||
`);
|
||||
container.append(item);
|
||||
@@ -2048,9 +2077,10 @@ export function initializePlotOptimizationBindings() {
|
||||
});
|
||||
|
||||
|
||||
panel.on('change.amily2_opt', '#amily2_opt_worldbook_checkbox_list input[type="checkbox"]', async function() {
|
||||
// Manual Selection Change
|
||||
panel.on('change.amily2_opt', '#amily2_opt_worldbook_checkbox_list input[type="checkbox"]:not(.amily2_opt_wb_auto_check)', async function() {
|
||||
const selected = [];
|
||||
panel.find('#amily2_opt_worldbook_checkbox_list input:checked').each(function() {
|
||||
panel.find('#amily2_opt_worldbook_checkbox_list input[type="checkbox"]:not(.amily2_opt_wb_auto_check):checked').each(function() {
|
||||
selected.push($(this).val());
|
||||
});
|
||||
|
||||
@@ -2058,6 +2088,17 @@ export function initializePlotOptimizationBindings() {
|
||||
await opt_loadWorldbookEntries(panel);
|
||||
});
|
||||
|
||||
// Auto Selection Change
|
||||
panel.on('change.amily2_opt', '#amily2_opt_worldbook_checkbox_list input.amily2_opt_wb_auto_check', async function() {
|
||||
const autoSelected = [];
|
||||
panel.find('#amily2_opt_worldbook_checkbox_list input.amily2_opt_wb_auto_check:checked').each(function() {
|
||||
autoSelected.push($(this).data('book'));
|
||||
});
|
||||
|
||||
await opt_saveSetting('plotOpt_autoSelectWorldbooks', autoSelected);
|
||||
await opt_loadWorldbookEntries(panel);
|
||||
});
|
||||
|
||||
panel.on('change.amily2_opt', '#amily2_opt_worldbook_entry_list_container input[type="checkbox"]', () => {
|
||||
opt_saveEnabledEntries();
|
||||
});
|
||||
|
||||
@@ -79,6 +79,10 @@ async function initializePanel(contentPanel, errorContainer) {
|
||||
const additionalPanelHtml = `<div id="amily2_additional_features_panel" style="display: none;">${additionalFeaturesContent}</div>`;
|
||||
mainContainer.append(additionalPanelHtml);
|
||||
|
||||
const textOptimizationContent = await $.get(`${extensionFolderPath}/assets/Amily2-TextOptimization.html`);
|
||||
const textOptimizationPanelHtml = `<div id="amily2_text_optimization_panel" style="display: none;">${textOptimizationContent}</div>`;
|
||||
mainContainer.append(textOptimizationPanelHtml);
|
||||
|
||||
const hanlinyuanContent = await $.get(`${extensionFolderPath}/assets/hanlinyuan.html`);
|
||||
const hanlinyuanPanelHtml = `<div id="amily2_hanlinyuan_panel" style="display: none;">${hanlinyuanContent}</div>`;
|
||||
mainContainer.append(hanlinyuanPanelHtml);
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -11,6 +11,7 @@ import { world_names, loadWorldInfo } from '/scripts/world-info.js';
|
||||
import { safeCharLorebooks, safeLorebookEntries } from '../core/tavernhelper-compatibility.js';
|
||||
import { characters, this_chid, eventSource, event_types } from "/script.js";
|
||||
import { fetchNccsModels, testNccsApiConnection } from '../core/api/NccsApi.js';
|
||||
import { showGraphVisualization } from '../core/relationship-graph/visualizer.js';
|
||||
|
||||
const isTouchDevice = () => window.matchMedia('(pointer: coarse)').matches;
|
||||
const getAllTablesContainer = () => document.getElementById('all-tables-container');
|
||||
@@ -330,9 +331,7 @@ export function renderTables() {
|
||||
|
||||
tables.forEach((tableData, tableIndex) => {
|
||||
const header = document.createElement('div');
|
||||
header.style.display = 'flex';
|
||||
header.style.justifyContent = 'space-between';
|
||||
header.style.alignItems = 'center';
|
||||
header.className = 'amily2-table-header-container';
|
||||
const title = document.createElement('h3');
|
||||
if (updatedTables.has(tableIndex)) {
|
||||
title.classList.add('table-updated'); // 【V15.2 新增】为更新的表格添加高亮
|
||||
@@ -383,7 +382,18 @@ export function renderTables() {
|
||||
cols.forEach(col => {
|
||||
totalWidth += parseInt(col.style.width, 10);
|
||||
});
|
||||
tableElement.style.width = `${totalWidth}px`;
|
||||
// Set min-width instead of fixed width to allow expansion
|
||||
tableElement.style.minWidth = '100%';
|
||||
if (totalWidth > 0) {
|
||||
// Only set explicit width if it exceeds the container (handled by min-width: 100% usually,
|
||||
// but here we set it as a base to ensure columns don't shrink below their defined width)
|
||||
tableElement.style.width = `${Math.max(totalWidth, 0)}px`;
|
||||
// Actually, to allow full width expansion, we should just use min-width and let CSS handle the rest
|
||||
// unless we want to force scrolling.
|
||||
// Let's try setting min-width to the calculated total, and width to 100%.
|
||||
tableElement.style.minWidth = `${totalWidth}px`;
|
||||
tableElement.style.width = '100%';
|
||||
}
|
||||
|
||||
const thead = tableElement.createTHead();
|
||||
const headerRow = thead.insertRow();
|
||||
@@ -798,6 +808,12 @@ function openRuleEditor(tableIndex) {
|
||||
<small class="notes">当表格总行数超过设定值时,将在表格底部显示警告。</small>
|
||||
</div>
|
||||
|
||||
<div class="rule-editor-field" style="border: 1px solid #444; padding: 10px; border-radius: 5px; margin-top: 10px;">
|
||||
<label for="rule-simplify-threshold" style="font-weight: bold; color: #ffcc00;">【实验性】历史内容简化阈值 (0为禁用)</label>
|
||||
<input type="number" id="rule-simplify-threshold" class="text_pole" min="0" value="${table.simplifyRowThreshold || 0}" style="width: 100px; margin-top: 10px;">
|
||||
<small class="notes">设置一个行号 X。在填表时,第 0 行到第 X-1 行的内容将被省略并替换为“已锁定”提示。这可以节省 Token 并防止 AI 修改旧数据。</small>
|
||||
</div>
|
||||
|
||||
<hr style="border-color: #444; margin: 10px 0;">
|
||||
|
||||
<div class="rule-editor-field">
|
||||
@@ -879,6 +895,7 @@ function openRuleEditor(tableIndex) {
|
||||
dialogElement.find('.popup-button-ok').on('click', () => {
|
||||
const newCharLimitRules = JSON.parse(dialogElement.find('#current-char-limit-rules').attr('data-rules') || '{}');
|
||||
const rowLimitValue = parseInt(dialogElement.find('#rule-row-limit-value').val(), 10);
|
||||
const simplifyThresholdValue = parseInt(dialogElement.find('#rule-simplify-threshold').val(), 10);
|
||||
|
||||
const newRules = {
|
||||
note: dialogElement.find('#rule-note').val(),
|
||||
@@ -887,6 +904,7 @@ function openRuleEditor(tableIndex) {
|
||||
rule_update: dialogElement.find('#rule-update').val(),
|
||||
charLimitRules: newCharLimitRules,
|
||||
rowLimitRule: rowLimitValue,
|
||||
simplifyRowThreshold: simplifyThresholdValue, // 保存新设置
|
||||
};
|
||||
TableManager.updateTableRules(tableIndex, newRules);
|
||||
closeDialog();
|
||||
@@ -1247,13 +1265,14 @@ export function bindTableEvents() {
|
||||
log('开始为表格视图绑定交互事件...', 'info');
|
||||
|
||||
const fillingModeRadios = panel.querySelectorAll('input[name="filling-mode"]');
|
||||
const contextSliderContainer = document.getElementById('context-reading-slider-container');
|
||||
const contextSlider = document.getElementById('context-reading-slider');
|
||||
const contextValueSpan = document.getElementById('context-reading-value');
|
||||
|
||||
const delaySliderContainer = document.getElementById('secondary-filler-delay-container');
|
||||
const delaySlider = document.getElementById('secondary-filler-delay-slider');
|
||||
const delayValueSpan = document.getElementById('secondary-filler-delay-value');
|
||||
// 获取新的分步填表控制容器
|
||||
const secondaryFillerControls = document.getElementById('secondary-filler-controls');
|
||||
|
||||
// 获取新的滑块元素
|
||||
const contextSlider = document.getElementById('secondary-filler-context');
|
||||
const batchSlider = document.getElementById('secondary-filler-batch');
|
||||
const bufferSlider = document.getElementById('secondary-filler-buffer');
|
||||
|
||||
const independentRulesContainer = document.getElementById('table-independent-rules-container');
|
||||
const independentRulesToggle = document.getElementById('table-independent-rules-enabled');
|
||||
@@ -1267,12 +1286,8 @@ export function bindTableEvents() {
|
||||
|
||||
const isSecondaryMode = currentMode === 'secondary-api';
|
||||
|
||||
if (contextSliderContainer) {
|
||||
contextSliderContainer.style.display = isSecondaryMode ? 'block' : 'none';
|
||||
}
|
||||
|
||||
if (delaySliderContainer) {
|
||||
delaySliderContainer.style.display = isSecondaryMode ? 'block' : 'none';
|
||||
if (secondaryFillerControls) {
|
||||
secondaryFillerControls.style.display = isSecondaryMode ? 'block' : 'none';
|
||||
}
|
||||
|
||||
if (independentRulesContainer) {
|
||||
@@ -1298,33 +1313,36 @@ export function bindTableEvents() {
|
||||
});
|
||||
});
|
||||
|
||||
if (contextSlider && contextValueSpan) {
|
||||
const contextReadingValue = extension_settings[extensionName]?.context_reading_level || 4;
|
||||
contextSlider.value = contextReadingValue;
|
||||
contextValueSpan.textContent = contextReadingValue;
|
||||
|
||||
contextSlider.addEventListener('input', function() {
|
||||
contextValueSpan.textContent = this.value;
|
||||
});
|
||||
// 绑定上下文深度输入框
|
||||
if (contextSlider) {
|
||||
const value = extension_settings[extensionName]?.secondary_filler_context || 2;
|
||||
contextSlider.value = value;
|
||||
|
||||
contextSlider.addEventListener('change', function() {
|
||||
updateAndSaveTableSetting('context_reading_level', parseInt(this.value, 10));
|
||||
toastr.info(`上下文读取级别已设置为 ${this.value}。`);
|
||||
updateAndSaveTableSetting('secondary_filler_context', parseInt(this.value, 10));
|
||||
toastr.info(`上下文深度已设置为 ${this.value}。`);
|
||||
});
|
||||
}
|
||||
|
||||
if (delaySlider && delayValueSpan) {
|
||||
const delayValue = extension_settings[extensionName]?.secondary_filler_delay || 0;
|
||||
delaySlider.value = delayValue;
|
||||
delayValueSpan.textContent = delayValue;
|
||||
|
||||
delaySlider.addEventListener('input', function() {
|
||||
delayValueSpan.textContent = this.value;
|
||||
});
|
||||
// 绑定填表批次输入框
|
||||
if (batchSlider) {
|
||||
const value = extension_settings[extensionName]?.secondary_filler_batch || 0;
|
||||
batchSlider.value = value;
|
||||
|
||||
delaySlider.addEventListener('change', function() {
|
||||
updateAndSaveTableSetting('secondary_filler_delay', parseInt(this.value, 10));
|
||||
toastr.info(`填表延迟已设置为 ${this.value} 楼层。`);
|
||||
batchSlider.addEventListener('change', function() {
|
||||
updateAndSaveTableSetting('secondary_filler_batch', parseInt(this.value, 10));
|
||||
toastr.info(`填表批次已设置为 ${this.value}。`);
|
||||
});
|
||||
}
|
||||
|
||||
// 绑定保留楼层输入框
|
||||
if (bufferSlider) {
|
||||
const value = extension_settings[extensionName]?.secondary_filler_buffer || 0;
|
||||
bufferSlider.value = value;
|
||||
|
||||
bufferSlider.addEventListener('change', function() {
|
||||
updateAndSaveTableSetting('secondary_filler_buffer', parseInt(this.value, 10));
|
||||
toastr.info(`保留楼层已设置为 ${this.value}。`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1353,6 +1371,7 @@ export function bindTableEvents() {
|
||||
bindBatchFillButton(); // 【新增】绑定批量填表按钮
|
||||
bindFloorFillButtons(); // 【新增】绑定楼层填表按钮
|
||||
bindReorganizeButton(); // 【新增】绑定重新整理按钮
|
||||
bindClearRecordsButton(); // 【新增】绑定清除记录按钮
|
||||
bindNccsApiEvents(); // 【新增】绑定Nccs API系统事件
|
||||
bindChatTableDisplaySetting(); // 【新增】绑定聊天内表格显示开关
|
||||
|
||||
@@ -1378,12 +1397,19 @@ export function bindTableEvents() {
|
||||
});
|
||||
}
|
||||
|
||||
const openGraphBtn = document.getElementById('amily2-open-relationship-graph-btn');
|
||||
const exportBtn = document.getElementById('amily2-export-preset-btn');
|
||||
const exportFullBtn = document.getElementById('amily2-export-preset-full-btn');
|
||||
const importBtn = document.getElementById('amily2-import-preset-btn');
|
||||
const importGlobalBtn = document.getElementById('amily2-import-global-preset-btn');
|
||||
const clearGlobalBtn = document.getElementById('amily2-clear-global-preset-btn');
|
||||
|
||||
if (openGraphBtn) {
|
||||
openGraphBtn.addEventListener('click', () => {
|
||||
showGraphVisualization();
|
||||
});
|
||||
}
|
||||
|
||||
if (exportBtn) {
|
||||
exportBtn.addEventListener('click', () => TableManager.exportPreset());
|
||||
}
|
||||
@@ -1613,13 +1639,63 @@ function bindReorganizeButton() {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { reorganizeTableContent } = await import('../core/table-system/reorganizer.js');
|
||||
await reorganizeTableContent();
|
||||
} catch (error) {
|
||||
console.error('[内存储司] 重新整理功能导入失败:', error);
|
||||
toastr.error('重新整理功能启动失败,请检查系统状态。');
|
||||
const tables = TableManager.getMemoryState();
|
||||
if (!tables || tables.length === 0) {
|
||||
toastr.warning('当前没有表格可供整理。');
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建表格选择列表 HTML
|
||||
const tableListHtml = tables.map((table, index) => `
|
||||
<div class="checkbox-item" style="margin-bottom: 8px; display: flex; align-items: center;">
|
||||
<input type="checkbox" id="reorg-table-${index}" value="${index}">
|
||||
<label for="reorg-table-${index}" style="margin-left: 8px; cursor: pointer;">${table.name}</label>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
const modalHtml = `
|
||||
<div style="display: flex; flex-direction: column; gap: 15px;">
|
||||
<p class="notes" style="color: #ffcc00;">建议:最好一次只选择一个表格,或少数几个相关联的表格进行整理。一次性处理过多表格可能会导致AI混淆或遗漏信息。</p>
|
||||
<p class="notes">请勾选需要AI重新整理和去重的表格:</p>
|
||||
<div style="max-height: 300px; overflow-y: auto; border: 1px solid #444; padding: 10px; border-radius: 5px; background: rgba(0,0,0,0.2);">
|
||||
${tableListHtml}
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<button id="reorg-select-all" class="menu_button small_button">全选</button>
|
||||
<button id="reorg-deselect-all" class="menu_button small_button">全不选</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
showHtmlModal('选择要整理的表格', modalHtml, {
|
||||
onOk: async (dialogElement) => {
|
||||
const selectedIndices = [];
|
||||
dialogElement.find('input[type="checkbox"]:checked').each(function() {
|
||||
selectedIndices.push(parseInt($(this).val(), 10));
|
||||
});
|
||||
|
||||
if (selectedIndices.length === 0) {
|
||||
toastr.warning('请至少选择一个表格。');
|
||||
return false; // 阻止关闭弹窗
|
||||
}
|
||||
|
||||
try {
|
||||
const { reorganizeTableContent } = await import('../core/table-system/reorganizer.js');
|
||||
await reorganizeTableContent(selectedIndices);
|
||||
} catch (error) {
|
||||
console.error('[内存储司] 重新整理功能导入失败:', error);
|
||||
toastr.error('重新整理功能启动失败,请检查系统状态。');
|
||||
}
|
||||
},
|
||||
onShow: (dialogElement) => {
|
||||
dialogElement.find('#reorg-select-all').on('click', () => {
|
||||
dialogElement.find('input[type="checkbox"]').prop('checked', true);
|
||||
});
|
||||
dialogElement.find('#reorg-deselect-all').on('click', () => {
|
||||
dialogElement.find('input[type="checkbox"]').prop('checked', false);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
reorganizeBtn.dataset.reorganizeEventBound = 'true';
|
||||
@@ -1627,6 +1703,37 @@ function bindReorganizeButton() {
|
||||
}
|
||||
}
|
||||
|
||||
function bindClearRecordsButton() {
|
||||
const clearBtn = document.getElementById('clear-records-btn');
|
||||
const floorInput = document.getElementById('clear-records-before-floor');
|
||||
|
||||
if (clearBtn && floorInput) {
|
||||
if (clearBtn.dataset.clearEventBound) return;
|
||||
|
||||
clearBtn.addEventListener('click', async () => {
|
||||
const floorIndex = parseInt(floorInput.value, 10);
|
||||
if (isNaN(floorIndex) || floorIndex < 0) {
|
||||
toastr.warning('请输入有效的楼层号。');
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm(`【警告】您确定要清除第 ${floorIndex} 楼之前的所有表格记录吗?\n\n此操作将永久删除这些消息中存储的表格快照,无法恢复。当前最新的表格状态不会受影响。`)) {
|
||||
try {
|
||||
const { clearTableRecordsBefore } = await import('../core/table-system/cleaner.js');
|
||||
const count = await clearTableRecordsBefore(floorIndex);
|
||||
toastr.success(`已成功清除 ${count} 条消息中的表格记录。`);
|
||||
} catch (error) {
|
||||
console.error('[内存储司] 清除记录失败:', error);
|
||||
toastr.error('清除记录失败,请检查控制台日志。');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
clearBtn.dataset.clearEventBound = 'true';
|
||||
log('"清除记录"按钮已成功绑定。', 'success');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function bindFloorFillButtons() {
|
||||
const selectedFloorsBtn = document.getElementById('fill-selected-floors-btn');
|
||||
@@ -2076,11 +2183,9 @@ function bindChatTableDisplaySetting() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize states from settings
|
||||
showInChatToggle.checked = settings.show_table_in_chat === true;
|
||||
continuousRenderToggle.checked = settings.render_on_every_message === true;
|
||||
|
||||
// Function to update the dependency
|
||||
const updateContinuousRenderState = () => {
|
||||
if (showInChatToggle.checked) {
|
||||
continuousRenderToggle.disabled = false;
|
||||
@@ -2091,18 +2196,14 @@ function bindChatTableDisplaySetting() {
|
||||
}
|
||||
};
|
||||
|
||||
// Initial state update
|
||||
updateContinuousRenderState();
|
||||
|
||||
// Event listener for the main toggle
|
||||
showInChatToggle.addEventListener('change', () => {
|
||||
settings.show_table_in_chat = showInChatToggle.checked;
|
||||
saveSettingsDebounced();
|
||||
toastr.info(`聊天内表格显示已${showInChatToggle.checked ? '开启' : '关闭'}。`);
|
||||
updateContinuousRenderState();
|
||||
});
|
||||
|
||||
// Event listener for the continuous render toggle
|
||||
continuousRenderToggle.addEventListener('change', () => {
|
||||
settings.render_on_every_message = continuousRenderToggle.checked;
|
||||
saveSettingsDebounced();
|
||||
|
||||
Reference in New Issue
Block a user