diff --git a/ui/table-bindings.js b/ui/table-bindings.js
index 6c05894..de86979 100644
--- a/ui/table-bindings.js
+++ b/ui/table-bindings.js
@@ -6,6 +6,7 @@ import { extension_settings, getContext } from '/scripts/extensions.js';
import { extensionName } from '../utils/settings.js';
import { saveSettingsDebounced } from '/script.js';
import { startBatchFilling } from '../core/table-system/batch-filler.js';
+import { showHtmlModal } from './page-window.js';
import { DEFAULT_AI_RULE_TEMPLATE, DEFAULT_AI_FLOW_TEMPLATE } from '../core/table-system/settings.js';
import { world_names, loadWorldInfo } from '/scripts/world-info.js';
import { safeCharLorebooks, safeLorebookEntries } from '../core/tavernhelper-compatibility.js';
@@ -490,6 +491,74 @@ export function renderTables() {
}
+function openTableRuleEditor() {
+ const settings = extension_settings[extensionName];
+ const tags = settings.table_tags_to_extract || '';
+ const exclusionRules = settings.table_exclusion_rules || [];
+
+ const rulesHtml = exclusionRules.map((rule, index) => `
+
+
+ -
+
+
+
+ `).join('');
+
+ const modalHtml = `
+
+
+
+
+ 仅提取指定XML标签的内容,例如填“content”,即提取...中的内容。
+
+
+
+
${rulesHtml}
+
+
移除所有被起始和结束标记包裹的内容(例如 OOC 部分)。
+
+
+ `;
+
+ const dialog = showHtmlModal('配置独立提取规则', modalHtml, {
+ onOk: () => {
+ const newTags = document.getElementById('table-tags-input').value;
+ updateAndSaveTableSetting('table_tags_to_extract', newTags);
+
+ const newExclusionRules = [];
+ document.querySelectorAll('#exclusion-rules-list .exclusion-rule-item').forEach(item => {
+ const start = item.querySelector('.rule-start').value.trim();
+ const end = item.querySelector('.rule-end').value.trim();
+ if (start && end) {
+ newExclusionRules.push({ start, end });
+ }
+ });
+ updateAndSaveTableSetting('table_exclusion_rules', newExclusionRules);
+ toastr.success('独立提取规则已保存。');
+ },
+ onShow: (dialogElement) => {
+ const rulesList = dialogElement.find('#exclusion-rules-list');
+
+ dialogElement.find('#add-exclusion-rule-btn').on('click', () => {
+ const newIndex = rulesList.children().length;
+ const newItemHtml = `
+
+
+ -
+
+
+
`;
+ rulesList.append(newItemHtml);
+ });
+
+ rulesList.on('click', '.remove-rule-btn', function() {
+ $(this).closest('.exclusion-rule-item').remove();
+ });
+ }
+ });
+}
+
function openRuleEditor(tableIndex) {
const tables = TableManager.getMemoryState();
if (!tables || !tables[tableIndex]) return;
@@ -884,6 +953,9 @@ export function bindTableEvents() {
const contextSliderContainer = document.getElementById('context-reading-slider-container');
const contextSlider = document.getElementById('context-reading-slider');
const contextValueSpan = document.getElementById('context-reading-value');
+ const independentRulesContainer = document.getElementById('table-independent-rules-container');
+ const independentRulesToggle = document.getElementById('table-independent-rules-enabled');
+ const configureRulesBtn = document.getElementById('table-configure-rules-btn');
const updateFillingModeUI = () => {
const currentMode = extension_settings[extensionName]?.filling_mode || 'main-api';
@@ -891,12 +963,18 @@ export function bindTableEvents() {
radio.checked = (radio.value === currentMode);
});
+ const isSecondaryMode = currentMode === 'secondary-api';
+
if (contextSliderContainer) {
- if (currentMode === 'secondary-api') {
- contextSliderContainer.style.display = 'block';
- } else {
- contextSliderContainer.style.display = 'none';
- }
+ contextSliderContainer.style.display = isSecondaryMode ? 'block' : 'none';
+ }
+
+ if (independentRulesContainer) {
+ independentRulesContainer.style.display = 'flex';
+ }
+
+ if (independentRulesToggle && configureRulesBtn) {
+ configureRulesBtn.style.display = independentRulesToggle.checked ? 'block' : 'none';
}
};
@@ -929,8 +1007,20 @@ export function bindTableEvents() {
});
}
+ if (independentRulesToggle) {
+ independentRulesToggle.checked = extension_settings[extensionName]?.table_independent_rules_enabled ?? false;
+ independentRulesToggle.addEventListener('change', () => {
+ updateAndSaveTableSetting('table_independent_rules_enabled', independentRulesToggle.checked);
+ updateFillingModeUI();
+ });
+ }
+
updateFillingModeUI();
+ if (configureRulesBtn) {
+ configureRulesBtn.addEventListener('click', openTableRuleEditor);
+ }
+
const renderAll = () => {
renderTables();
bindInjectionSettings();
@@ -944,6 +1034,7 @@ export function bindTableEvents() {
bindReorganizeButton(); // 【新增】绑定重新整理按钮
bindTemplateEditors(); // 【新增】为新的指令模板编辑器绑定事件
bindNccsApiEvents(); // 【新增】绑定Nccs API系统事件
+ bindChatTableDisplaySetting(); // 【新增】绑定聊天内表格显示开关
const navDeck = document.querySelector('#amily2_memorisation_forms_panel .sinan-navigation-deck');
if (navDeck) {
@@ -1121,12 +1212,24 @@ export function bindTableEvents() {
const colIndex = parseInt(target.dataset.colIndex, 10);
const newValue = target.textContent;
+ const hScroll = tableElement.scrollLeft;
+ const scrollContainer = allTablesContainer.closest('.hly-scroll');
+ const vScroll = scrollContainer ? scrollContainer.scrollTop : 0;
+
TableManager.addHighlight(tableIndex, rowIndex, colIndex);
const dataToUpdate = { [colIndex]: newValue };
TableManager.updateRow(tableIndex, rowIndex, dataToUpdate);
renderAll();
+ const newTableElement = document.getElementById(`amily2-table-${tableIndex}`);
+ if (newTableElement) {
+ newTableElement.scrollLeft = hScroll;
+ }
+ if (scrollContainer) {
+ scrollContainer.scrollTop = vScroll;
+ }
+
}, true);
}
@@ -1602,3 +1705,23 @@ function bindNccsApiEvents() {
log('Nccs API事件绑定完成', 'success');
}
+
+function bindChatTableDisplaySetting() {
+ const settings = extension_settings[extensionName];
+ const toggle = document.getElementById('show-table-in-chat-toggle');
+
+ if (!toggle) {
+ log('找不到“聊天内显示表格”的开关,绑定失败。', 'warn');
+ return;
+ }
+
+ toggle.checked = settings.show_table_in_chat === true;
+
+ toggle.addEventListener('change', () => {
+ settings.show_table_in_chat = toggle.checked;
+ saveSettingsDebounced();
+ toastr.info(`聊天内表格显示已${toggle.checked ? '开启' : '关闭'}。`);
+ });
+
+ log('“聊天内显示表格”开关已成功绑定。', 'success');
+}