您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Пользовательский скрипт, добавляющий в список подключений на странице online.sbis.ru/integration_config/?Page=7 удобный интерфейс для выбора и удаления подключений напрямую, без необходимости удаления их вручную через сайт.
// ==UserScript== // @author Evgeniy Lykhov // @name Integration Config - Delete connection // @description Пользовательский скрипт, добавляющий в список подключений на странице online.sbis.ru/integration_config/?Page=7 удобный интерфейс для выбора и удаления подключений напрямую, без необходимости удаления их вручную через сайт. // @version 23-07-2025 // @match https://online.sbis.ru/integration_config/?Page=7* // @match https://online.sbis.ru/integration_config/?service=extExch&Page=7* // @match https://fix-online.sbis.ru/integration_config/?Page=7* // @icon https://cdn2.sbis.ru/cdn/SabyLogo/1.0.7/favicon/favicon.ico?v=1 // @run-at document-end // @namespace https://greasyfork.org/users/1497438 // ==/UserScript== (async function() { // 0. Вставка CSS для фиксированной ширины колонки, центрирования и отступов кнопок const style = document.createElement('style'); style.textContent = ` .controls-DataGridView__th.DataGridView__td__checkBox, .controls-DataGridView__td.DataGridView__td__checkBox { width: 24px !important; text-align: center !important; min-width: 24px !important; max-width: 24px !important;} .controls-DataGridView__td.DataGridView__td__checkBox input { width: 50px; height: 17px; cursor: pointer; } .controls-button { display: inline-block; outline: 0; line-height: normal; box-sizing: border-box; font-family: Inter; font-size: 14px; font-weight: 400; position: relative; box-shadow: none; border: 1px solid #587ab0; min-width: 48px; text-shadow: none; -webkit-user-select: none; user-select: none; color: #000; background: #fff; height: 24px; padding: 0 11px; border-radius: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .controls-button:hover { background: #e1ecf6; } #sbis-panel { display: flex; justify-content: space-between; align-items: center; margin: 0px 25px; gap: 10px; } #sbis-panel-left, #sbis-panel-right { display: flex; align-items: center; justify-content: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; gap: 10px; } #sbis-header-counter { font-size: 16px; min-width: 110px; } `; document.head.append(style); // Ждём появления целевой таблицы function waitFor(selector, timeout = 5000) { return new Promise((resolve, reject) => { const el = document.querySelector(selector); if (el) return resolve(el); const obs = new MutationObserver(() => { const found = document.querySelector(selector); if (found) { obs.disconnect(); resolve(found); } }); obs.observe(document.body, { childList: true, subtree: true }); setTimeout(() => { obs.disconnect(); reject(new Error(`Не найдена таблица ${selector}`)); }, timeout); }); } try { const connectionLimitForDeletion = 50; const table = await waitFor('.controls-DataGridView__table.ws-sticky-header__table'); const tbody = table.querySelector('tbody'); // 1. Вставка колонки для чекбоксов в colgroup function insertCol() { const cg = table.querySelector('colgroup'); if (!cg || cg.querySelector('col[data-inserted]')) return; const newCol = document.createElement('col'); newCol.width = '24px'; newCol.setAttribute('data-inserted', 'true'); cg.insertBefore(newCol, cg.firstElementChild); } insertCol(); // Следим за перерисовкой colgroup new MutationObserver(() => insertCol()) .observe(table.querySelector('colgroup').parentNode, { childList: true }); // 2. Добавление заголовочного <th> под чекбоксы function insertHeaderCell() { const theadRow = table.querySelector('thead tr'); if (!theadRow || theadRow.querySelector('th.DataGridView__td__checkBox')) return; const th = document.createElement('th'); th.className = 'controls-DataGridView__th DataGridView__td__checkBox'; th.style.textAlign = 'center'; th.style.width = '24px'; theadRow.insertBefore(th, theadRow.firstElementChild); } insertHeaderCell(); new MutationObserver(() => insertHeaderCell()) .observe(table, { childList: true, subtree: true }); // 3. Добавление чекбокса в каждую строку function addRowCheckbox(tr) { if (tr.querySelector('.DataGridView__td__checkBox input')) return; const id = tr.getAttribute('data-id'); if (!id) return; const td = document.createElement('td'); td.className = 'controls-DataGridView__td DataGridView__td__checkBox'; const cb = document.createElement('input'); cb.type = 'checkbox'; cb.dataset.id = id; cb.style.alignContent = 'center'; cb.addEventListener('click', e => e.stopPropagation()); td.append(cb); tr.insertBefore(td, tr.firstElementChild); } tbody.querySelectorAll('tr[data-id]').forEach(addRowCheckbox); new MutationObserver(muts => muts.forEach(m => m.addedNodes.forEach(n => n.nodeType === 1 && n.matches('tr[data-id]') && addRowCheckbox(n)))) .observe(tbody, { childList: true }); function updateHeaderCounter() { const count = tbody.querySelectorAll( 'td.DataGridView__td__checkBox input:checked' ).length; const counter = document.getElementById('sbis-header-counter'); if (counter) counter.textContent = `Выбрано: ${count}`; } tbody.addEventListener('change', e => { if (e.target.matches('td.DataGridView__td__checkBox input')) { updateHeaderCounter(); } }); // 4. Панель кнопок над списком, справа от поиска function insertPanel() { if (document.getElementById('sbis-panel')) return; const searchCell = document.querySelector('.controls-Browser__tableCell-search'); if (!searchCell || !searchCell.parentNode) return; const container = searchCell.parentNode; const panel = document.createElement('div'); panel.id = 'sbis-panel'; const panelLeft = document.createElement('div'); panelLeft.id = 'sbis-panel-left'; const panelRight = document.createElement('div'); panelRight.id = 'sbis-panel-right'; const btnAll = document.createElement('button'); btnAll.textContent = 'Выбрать все'; btnAll.className = 'controls-button'; btnAll.onclick = () => { tbody.querySelectorAll('td.DataGridView__td__checkBox input').forEach(cb => cb.checked = true); updateHeaderCounter(); } const btnNone = document.createElement('button'); btnNone.textContent = 'Снять все'; btnNone.className = 'controls-button'; btnNone.onclick = () => { tbody.querySelectorAll('td.DataGridView__td__checkBox input').forEach(cb => cb.checked = false); updateHeaderCounter(); } const btnDelete = document.createElement('button'); btnDelete.textContent = 'Удалить выбранные'; btnDelete.className = 'controls-button'; btnDelete.onclick = () => { const checked = Array.from(tbody.querySelectorAll('td.DataGridView__td__checkBox input:checked')); const total = checked.length; if (!total) { alert('Не выбрано ни одного подключения для удаления.'); return; } else if (total <= connectionLimitForDeletion) { if (!confirm(`Вы удаляете ${total} подключений. Продолжить?`)) return; } else if (total > connectionLimitForDeletion) { if (!confirm(`Будут удалены первые ${connectionLimitForDeletion} из ${total} подключений - остальные останутся.\n` + `Необходимо будет обновить список и повторить удаление оставщихся.\n` + `Продолжить?`)) return; } const toDelete = checked.slice(0, 50); require(['Types/source'], src => { const service = new src.SbisService({ endpoint: { address: '/integration_config/service/', contract: 'IntegrationConnection' } }); toDelete.forEach(cb => { service.call('DeleteConnection', { id: cb.dataset.id }); console.log(`Удалено подключение: ${cb.dataset.id}`); }); tbody.querySelectorAll('td.DataGridView__td__checkBox input').forEach(cb => cb.checked = false); updateHeaderCounter(); }); }; const counter = document.createElement('span'); counter.id = 'sbis-header-counter'; counter.textContent = 'Выбрано: 0'; panelLeft.append(counter); panelLeft.append(btnAll, btnNone); panelRight.append(btnDelete); panel.append(panelLeft, panelRight); container.insertBefore(panel, searchCell.nextSibling); } insertPanel(); new MutationObserver(insertPanel).observe(document.body, { childList: true, subtree: true }); } catch (error) { console.error('[Userscript] Ошибка:', error); } })();