mirror of
https://github.com/Wx-2025/ST-Amily2-Chat-Optimisation.git
synced 2026-06-06 15:05:51 +00:00
Update table-bindings.js
This commit is contained in:
@@ -15,6 +15,8 @@ import { fetchNccsModels, testNccsApiConnection } from '../core/api/NccsApi.js';
|
|||||||
const isTouchDevice = () => window.matchMedia('(pointer: coarse)').matches;
|
const isTouchDevice = () => window.matchMedia('(pointer: coarse)').matches;
|
||||||
const getAllTablesContainer = () => document.getElementById('all-tables-container');
|
const getAllTablesContainer = () => document.getElementById('all-tables-container');
|
||||||
|
|
||||||
|
let isResizing = false;
|
||||||
|
|
||||||
|
|
||||||
function toggleRowContextMenu(event) {
|
function toggleRowContextMenu(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -23,63 +25,104 @@ function toggleRowContextMenu(event) {
|
|||||||
const targetTd = event.target.closest('td.index-col');
|
const targetTd = event.target.closest('td.index-col');
|
||||||
if (!targetTd) return;
|
if (!targetTd) return;
|
||||||
|
|
||||||
const menu = targetTd.querySelector('.amily2-context-menu');
|
const tableWrapper = targetTd.closest('.amily2-table-wrapper');
|
||||||
if (!menu) return;
|
if (!tableWrapper) return;
|
||||||
|
|
||||||
const isActive = menu.classList.contains('amily2-menu-active');
|
const isActive = targetTd.classList.contains('amily2-menu-open');
|
||||||
|
document.querySelectorAll('.amily2-menu-open').forEach(openEl => {
|
||||||
document.querySelectorAll('.amily2-context-menu.amily2-menu-active').forEach(activeMenu => {
|
if (openEl !== targetTd) {
|
||||||
activeMenu.classList.remove('amily2-menu-active');
|
openEl.classList.remove('amily2-menu-open');
|
||||||
|
const otherWrapper = openEl.closest('.amily2-table-wrapper');
|
||||||
|
if (otherWrapper) {
|
||||||
|
otherWrapper.style.overflowX = 'auto';
|
||||||
|
otherWrapper.style.zIndex = '';
|
||||||
|
otherWrapper.style.position = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
targetTd.classList.toggle('amily2-menu-open');
|
||||||
if (!isActive) {
|
if (targetTd.classList.contains('amily2-menu-open')) {
|
||||||
menu.classList.add('amily2-menu-active');
|
tableWrapper.style.overflowX = 'visible';
|
||||||
|
tableWrapper.style.position = 'relative';
|
||||||
|
tableWrapper.style.zIndex = '10';
|
||||||
|
} else {
|
||||||
|
tableWrapper.style.overflowX = 'auto';
|
||||||
|
tableWrapper.style.position = '';
|
||||||
|
tableWrapper.style.zIndex = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeMenu = (e) => {
|
const closeMenu = (e) => {
|
||||||
if (!menu.contains(e.target)) {
|
if (!targetTd.contains(e.target)) {
|
||||||
menu.classList.remove('amily2-menu-active');
|
targetTd.classList.remove('amily2-menu-open');
|
||||||
|
tableWrapper.style.overflowX = 'auto';
|
||||||
|
tableWrapper.style.position = '';
|
||||||
|
tableWrapper.style.zIndex = '';
|
||||||
document.removeEventListener('click', closeMenu, true);
|
document.removeEventListener('click', closeMenu, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setTimeout(() => {
|
if (targetTd.classList.contains('amily2-menu-open')) {
|
||||||
if (menu.classList.contains('amily2-menu-active')) {
|
setTimeout(() => {
|
||||||
document.addEventListener('click', closeMenu, true);
|
document.addEventListener('click', closeMenu, true);
|
||||||
}
|
}, 0);
|
||||||
}, 0);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function toggleColumnContextMenu(event) {
|
function toggleColumnContextMenu(event) {
|
||||||
|
if (isResizing || event.target.classList.contains('amily2-resizer')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
const targetTh = event.target.closest('th');
|
const targetTh = event.target.closest('th');
|
||||||
if (!targetTh) return;
|
if (!targetTh) return;
|
||||||
|
|
||||||
const isActive = targetTh.classList.contains('amily2-menu-open');
|
const tableWrapper = targetTh.closest('.amily2-table-wrapper');
|
||||||
|
if (!tableWrapper) return;
|
||||||
|
|
||||||
|
const isActive = targetTh.classList.contains('amily2-menu-open');
|
||||||
document.querySelectorAll('th.amily2-menu-open').forEach(openTh => {
|
document.querySelectorAll('th.amily2-menu-open').forEach(openTh => {
|
||||||
openTh.classList.remove('amily2-menu-open');
|
if (openTh !== targetTh) {
|
||||||
|
openTh.classList.remove('amily2-menu-open');
|
||||||
|
const otherWrapper = openTh.closest('.amily2-table-wrapper');
|
||||||
|
if (otherWrapper) {
|
||||||
|
otherWrapper.style.overflowX = 'auto';
|
||||||
|
otherWrapper.style.zIndex = '';
|
||||||
|
otherWrapper.style.position = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isActive) {
|
targetTh.classList.toggle('amily2-menu-open');
|
||||||
targetTh.classList.add('amily2-menu-open');
|
|
||||||
|
if (targetTh.classList.contains('amily2-menu-open')) {
|
||||||
|
tableWrapper.style.overflowX = 'visible';
|
||||||
|
tableWrapper.style.position = 'relative';
|
||||||
|
tableWrapper.style.zIndex = '10';
|
||||||
|
} else {
|
||||||
|
tableWrapper.style.overflowX = 'auto';
|
||||||
|
tableWrapper.style.position = '';
|
||||||
|
tableWrapper.style.zIndex = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeMenu = (e) => {
|
const closeMenu = (e) => {
|
||||||
if (!targetTh.contains(e.target)) {
|
if (!targetTh.contains(e.target)) {
|
||||||
targetTh.classList.remove('amily2-menu-open');
|
targetTh.classList.remove('amily2-menu-open');
|
||||||
|
tableWrapper.style.overflowX = 'auto';
|
||||||
|
tableWrapper.style.position = '';
|
||||||
|
tableWrapper.style.zIndex = '';
|
||||||
document.removeEventListener('click', closeMenu, true);
|
document.removeEventListener('click', closeMenu, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setTimeout(() => {
|
// If the menu was opened, set up the listener to close it
|
||||||
if (targetTh.classList.contains('amily2-menu-open')) {
|
if (targetTh.classList.contains('amily2-menu-open')) {
|
||||||
|
setTimeout(() => {
|
||||||
document.addEventListener('click', closeMenu, true);
|
document.addEventListener('click', closeMenu, true);
|
||||||
}
|
}, 0);
|
||||||
}, 0);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -297,12 +340,34 @@ export function renderTables() {
|
|||||||
header.appendChild(controls);
|
header.appendChild(controls);
|
||||||
container.appendChild(header);
|
container.appendChild(header);
|
||||||
|
|
||||||
|
const tableWrapper = document.createElement('div');
|
||||||
|
tableWrapper.className = 'amily2-table-wrapper';
|
||||||
|
|
||||||
const tableElement = document.createElement('table');
|
const tableElement = document.createElement('table');
|
||||||
tableElement.style.display = 'block';
|
|
||||||
tableElement.style.overflowX = 'auto';
|
|
||||||
tableElement.id = `amily2-table-${tableIndex}`;
|
tableElement.id = `amily2-table-${tableIndex}`;
|
||||||
tableElement.dataset.tableIndex = tableIndex;
|
tableElement.dataset.tableIndex = tableIndex;
|
||||||
|
|
||||||
|
const colgroup = document.createElement('colgroup');
|
||||||
|
const indexCol = document.createElement('col');
|
||||||
|
indexCol.style.width = '40px';
|
||||||
|
colgroup.appendChild(indexCol);
|
||||||
|
|
||||||
|
if (tableData.headers) {
|
||||||
|
tableData.headers.forEach((_, colIndex) => {
|
||||||
|
const col = document.createElement('col');
|
||||||
|
const colWidth = (tableData.columnWidths && tableData.columnWidths[colIndex]) ? tableData.columnWidths[colIndex] : 90;
|
||||||
|
col.style.width = `${colWidth}px`;
|
||||||
|
colgroup.appendChild(col);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
tableElement.appendChild(colgroup);
|
||||||
|
let totalWidth = 0;
|
||||||
|
const cols = colgroup.querySelectorAll('col');
|
||||||
|
cols.forEach(col => {
|
||||||
|
totalWidth += parseInt(col.style.width, 10);
|
||||||
|
});
|
||||||
|
tableElement.style.width = `${totalWidth}px`;
|
||||||
|
|
||||||
const thead = tableElement.createTHead();
|
const thead = tableElement.createTHead();
|
||||||
const headerRow = thead.insertRow();
|
const headerRow = thead.insertRow();
|
||||||
|
|
||||||
@@ -315,7 +380,7 @@ export function renderTables() {
|
|||||||
if (!tableData.rows || tableData.rows.length === 0) {
|
if (!tableData.rows || tableData.rows.length === 0) {
|
||||||
const headerMenu = document.createElement('div');
|
const headerMenu = document.createElement('div');
|
||||||
headerMenu.className = 'amily2-context-menu amily2-header-menu';
|
headerMenu.className = 'amily2-context-menu amily2-header-menu';
|
||||||
headerMenu.style.display = 'none';
|
headerMenu.style.display = 'none'; // 默认隐藏
|
||||||
|
|
||||||
const addRowButton = document.createElement('button');
|
const addRowButton = document.createElement('button');
|
||||||
addRowButton.innerHTML = '<i class="fas fa-plus-circle"></i> 创建第一行';
|
addRowButton.innerHTML = '<i class="fas fa-plus-circle"></i> 创建第一行';
|
||||||
@@ -398,6 +463,57 @@ export function renderTables() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
th.appendChild(menu);
|
th.appendChild(menu);
|
||||||
|
|
||||||
|
const resizer = document.createElement('div');
|
||||||
|
resizer.className = 'amily2-resizer';
|
||||||
|
th.appendChild(resizer);
|
||||||
|
|
||||||
|
const startResize = (startEvent) => {
|
||||||
|
startEvent.preventDefault();
|
||||||
|
startEvent.stopPropagation();
|
||||||
|
|
||||||
|
isResizing = true;
|
||||||
|
|
||||||
|
const table = startEvent.target.closest('table');
|
||||||
|
const th = startEvent.target.parentElement;
|
||||||
|
const col = table.querySelector(`colgroup > col:nth-child(${th.cellIndex + 1})`);
|
||||||
|
|
||||||
|
const isTouchEvent = startEvent.type.startsWith('touch');
|
||||||
|
const startX = isTouchEvent ? startEvent.touches[0].clientX : startEvent.clientX;
|
||||||
|
const startWidth = th.offsetWidth;
|
||||||
|
|
||||||
|
const onMove = (moveEvent) => {
|
||||||
|
const currentX = isTouchEvent ? moveEvent.touches[0].clientX : moveEvent.clientX;
|
||||||
|
const newWidth = startWidth + (currentX - startX);
|
||||||
|
if (newWidth > 50) {
|
||||||
|
col.style.width = `${newWidth}px`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEnd = () => {
|
||||||
|
document.removeEventListener('mousemove', onMove);
|
||||||
|
document.removeEventListener('mouseup', onEnd);
|
||||||
|
document.removeEventListener('touchmove', onMove);
|
||||||
|
document.removeEventListener('touchend', onEnd);
|
||||||
|
|
||||||
|
const finalWidth = parseInt(col.style.width, 10);
|
||||||
|
TableManager.updateColumnWidth(tableIndex, colIndex, finalWidth);
|
||||||
|
|
||||||
|
setTimeout(() => { isResizing = false; }, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isTouchEvent) {
|
||||||
|
document.addEventListener('touchmove', onMove, { passive: false });
|
||||||
|
document.addEventListener('touchend', onEnd);
|
||||||
|
} else {
|
||||||
|
document.addEventListener('mousemove', onMove);
|
||||||
|
document.addEventListener('mouseup', onEnd);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
resizer.addEventListener('mousedown', startResize);
|
||||||
|
resizer.addEventListener('touchstart', startResize, { passive: false });
|
||||||
|
|
||||||
headerRow.appendChild(th);
|
headerRow.appendChild(th);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -476,7 +592,8 @@ export function renderTables() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
container.appendChild(tableElement);
|
tableWrapper.appendChild(tableElement);
|
||||||
|
container.appendChild(tableWrapper);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (placeholder) {
|
if (placeholder) {
|
||||||
@@ -674,6 +791,8 @@ function openRuleEditor(tableIndex) {
|
|||||||
toastr.warning('请选择一个列。');
|
toastr.warning('请选择一个列。');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 允许输入0,但0意味着“无限制”,所以我们不添加规则。
|
||||||
if (isNaN(limitValue) || limitValue < 0) {
|
if (isNaN(limitValue) || limitValue < 0) {
|
||||||
toastr.warning('请输入一个有效的字数限制(大于等于0)。');
|
toastr.warning('请输入一个有效的字数限制(大于等于0)。');
|
||||||
return;
|
return;
|
||||||
@@ -1223,6 +1342,7 @@ export function bindTableEvents() {
|
|||||||
allTablesContainer.addEventListener('click', (event) => {
|
allTablesContainer.addEventListener('click', (event) => {
|
||||||
const th = event.target.closest('th');
|
const th = event.target.closest('th');
|
||||||
if (th && th.classList.contains('index-col')) {
|
if (th && th.classList.contains('index-col')) {
|
||||||
|
// 处理表头 # 号的点击(用于空表格添加首行)
|
||||||
toggleHeaderIndexContextMenu(event);
|
toggleHeaderIndexContextMenu(event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1310,9 +1430,10 @@ export function bindTableEvents() {
|
|||||||
const colIndex = parseInt(target.dataset.colIndex, 10);
|
const colIndex = parseInt(target.dataset.colIndex, 10);
|
||||||
const newValue = target.textContent;
|
const newValue = target.textContent;
|
||||||
|
|
||||||
const hScroll = tableElement.scrollLeft;
|
// Correctly save scroll positions before re-rendering
|
||||||
const scrollContainer = allTablesContainer.closest('.hly-scroll');
|
const tableWrapper = tableElement.closest('.amily2-table-wrapper');
|
||||||
const vScroll = scrollContainer ? scrollContainer.scrollTop : 0;
|
const hScroll = tableWrapper ? tableWrapper.scrollLeft : 0;
|
||||||
|
const vScroll = allTablesContainer.scrollTop;
|
||||||
|
|
||||||
TableManager.addHighlight(tableIndex, rowIndex, colIndex);
|
TableManager.addHighlight(tableIndex, rowIndex, colIndex);
|
||||||
const dataToUpdate = { [colIndex]: newValue };
|
const dataToUpdate = { [colIndex]: newValue };
|
||||||
@@ -1320,13 +1441,12 @@ export function bindTableEvents() {
|
|||||||
|
|
||||||
renderAll();
|
renderAll();
|
||||||
|
|
||||||
const newTableElement = document.getElementById(`amily2-table-${tableIndex}`);
|
// Correctly restore scroll positions after re-rendering
|
||||||
if (newTableElement) {
|
const newTableWrapper = document.getElementById(`amily2-table-${tableIndex}`)?.closest('.amily2-table-wrapper');
|
||||||
newTableElement.scrollLeft = hScroll;
|
if (newTableWrapper) {
|
||||||
}
|
newTableWrapper.scrollLeft = hScroll;
|
||||||
if (scrollContainer) {
|
|
||||||
scrollContainer.scrollTop = vScroll;
|
|
||||||
}
|
}
|
||||||
|
allTablesContainer.scrollTop = vScroll;
|
||||||
|
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
@@ -1849,7 +1969,6 @@ function bindChatTableDisplaySetting() {
|
|||||||
}
|
}
|
||||||
showInChatToggle.checked = settings.show_table_in_chat === true;
|
showInChatToggle.checked = settings.show_table_in_chat === true;
|
||||||
continuousRenderToggle.checked = settings.render_on_every_message === true;
|
continuousRenderToggle.checked = settings.render_on_every_message === true;
|
||||||
|
|
||||||
const updateContinuousRenderState = () => {
|
const updateContinuousRenderState = () => {
|
||||||
if (showInChatToggle.checked) {
|
if (showInChatToggle.checked) {
|
||||||
continuousRenderToggle.disabled = false;
|
continuousRenderToggle.disabled = false;
|
||||||
@@ -1859,9 +1978,7 @@ function bindChatTableDisplaySetting() {
|
|||||||
continuousRenderToggle.closest('.control-block-with-switch').style.opacity = '0.5';
|
continuousRenderToggle.closest('.control-block-with-switch').style.opacity = '0.5';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
updateContinuousRenderState();
|
updateContinuousRenderState();
|
||||||
|
|
||||||
showInChatToggle.addEventListener('change', () => {
|
showInChatToggle.addEventListener('change', () => {
|
||||||
settings.show_table_in_chat = showInChatToggle.checked;
|
settings.show_table_in_chat = showInChatToggle.checked;
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
|
|||||||
Reference in New Issue
Block a user