您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在报告页面的"说明 (必填):"输入框上方添加快捷输入按钮,可自定义按钮和文本。
// ==UserScript== // @name 快捷输入助手 for DIC Music Reports // @namespace http://tampermonkey.net/ // @version 1.4 // @description 在报告页面的"说明 (必填):"输入框上方添加快捷输入按钮,可自定义按钮和文本。 // @author Your Name (You can change this) // @match https://dicmusic.com/reportsv2.php?action=report&id=* // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant GM_registerMenuCommand // @require https://code.jquery.com/jquery-3.6.0.min.js // ==/UserScript== /* globals $, GM_setValue, GM_getValue, GM_addStyle, GM_registerMenuCommand */ (function() { 'use strict'; const MAX_BUTTONS = 50; const BUTTON_CONFIG_KEY = 'dicmusic_quick_input_buttons'; const SCRIPT_BUTTON_CONTAINER_ID = 'quick-input-buttons-container'; // ID for the div holding buttons const SCRIPT_BUTTON_TR_ID = 'quick-input-buttons-tr'; // ID for the TR holding the button container const SETTINGS_MODAL_ID = 'quick-input-settings-modal'; const defaultButtons = [ { name: '格式错误', text: '种子格式不符合规则,具体说明:' }, { name: '信息不全', text: '种子信息描述不完整或有误,具体说明:' } ]; let buttonsConfig = GM_getValue(BUTTON_CONFIG_KEY, defaultButtons); function addGlobalStyles() { GM_addStyle(` /* Div that holds all buttons */ #${SCRIPT_BUTTON_CONTAINER_ID} { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 10px; /* Applies if in fallback mode */ } /* The Table Cell that will contain the button div, if placed in table */ #${SCRIPT_BUTTON_TR_ID} td { padding-bottom: 10px; /* Space below button bar */ border: none; } #${SCRIPT_BUTTON_CONTAINER_ID} button { background-color: #f0f0f0; border: 1px solid #bbb; color: #333; padding: 5px 10px; border-radius: 3px; cursor: pointer; font-size: 0.9em; line-height: 1.2; white-space: nowrap; } #${SCRIPT_BUTTON_CONTAINER_ID} button:hover { background-color: #e0e0e0; border-color: #999; } #${SCRIPT_BUTTON_CONTAINER_ID} .settings-cog-btn { padding: 5px 8px; font-size: 1em; } #${SETTINGS_MODAL_ID} { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: white; border: 1px solid #ccc; padding: 20px; z-index: 10001; box-shadow: 0 4px 8px rgba(0,0,0,0.1); width: 500px; max-height: 80vh; overflow-y: auto; font-size: 14px; } #${SETTINGS_MODAL_ID} h3 { margin-top: 0; border-bottom: 1px solid #eee; padding-bottom: 10px; } #${SETTINGS_MODAL_ID} .button-entry { display: flex; margin-bottom: 10px; align-items: center; } #${SETTINGS_MODAL_ID} .button-entry input[type="text"] { flex-grow: 1; margin-right: 10px; padding: 6px; border: 1px solid #ccc; border-radius: 3px; } #${SETTINGS_MODAL_ID} .button-entry input[name="btn-name"] { max-width: 120px; } #${SETTINGS_MODAL_ID} .action-buttons button, #${SETTINGS_MODAL_ID} .button-entry button { padding: 6px 12px; background-color: #5cb85c; color: white; border: none; border-radius: 3px; cursor: pointer; margin-left: 5px; } #${SETTINGS_MODAL_ID} .button-entry .remove-btn { background-color: #d9534f; } #${SETTINGS_MODAL_ID} .action-buttons button:hover, #${SETTINGS_MODAL_ID} .button-entry button:hover { opacity: 0.9; } #${SETTINGS_MODAL_ID} .action-buttons { margin-top: 20px; text-align: right; } #${SETTINGS_MODAL_ID} #add-button-row { background-color: #4682B4; } .settings-modal-backdrop { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); z-index: 10000; } `); } function findCommentsLabelAndTextarea() { const dynamicForm = $('#dynamic_form'); if (!dynamicForm.length) return null; let commentsLabelTd = null; dynamicForm.find('table.layout td.label').each(function() { if ($(this).text().includes('说明')) { commentsLabelTd = $(this); return false; } }); if (!commentsLabelTd || !commentsLabelTd.length) return null; const textarea = commentsLabelTd.next('td').find('textarea'); if (!textarea.length) return null; return { labelTd: commentsLabelTd, textarea: textarea }; } function insertTextIntoTextarea(textToInsert) { const elements = findCommentsLabelAndTextarea(); if (elements && elements.textarea) { const textarea = elements.textarea[0]; const currentText = textarea.value; if (currentText.length > 0 && !currentText.endsWith('\n')) { textarea.value += '\n' + textToInsert; } else { textarea.value += textToInsert; } textarea.focus(); textarea.dispatchEvent(new Event('input', { bubbles: true })); textarea.dispatchEvent(new Event('change', { bubbles: true })); } else { console.warn("QuickInputHelper: Textarea not found for insertion."); } } function createButtonElement(config) { const button = $('<button type="button"></button>'); button.text(config.name); button.attr('title', `点击插入: "${config.text}"`); button.on('click', function() { insertTextIntoTextarea(config.text); }); return button; } function renderButtons() { // Only remove elements specifically created by this script $(`#${SCRIPT_BUTTON_TR_ID}`).remove(); // Removes the TR if it exists $(`#${SCRIPT_BUTTON_CONTAINER_ID}`).remove(); // Removes the div if it exists (e.g. from fallback) const $buttonHostDiv = $(`<div id="${SCRIPT_BUTTON_CONTAINER_ID}"></div>`); const $settingsButton = $('<button type="button" class="settings-cog-btn" title="设置快捷输入按钮"><i class="fas fa-cog"></i></button>'); $settingsButton.on('click', openSettingsPanel); $buttonHostDiv.append($settingsButton); buttonsConfig.forEach(config => { $buttonHostDiv.append(createButtonElement(config)); }); const elements = findCommentsLabelAndTextarea(); if (elements && elements.labelTd) { const $parentTR = elements.labelTd.closest('tr'); if ($parentTR.length) { let colspan = $parentTR.children('td').length; if (colspan === 0 && $parentTR.parent().children('tr:first-child').length) { colspan = $parentTR.parent().children('tr:first-child').children('td').length; } if (colspan < 1) colspan = 1; const $containerTR = $(`<tr id="${SCRIPT_BUTTON_TR_ID}"><td colspan="${colspan}"></td></tr>`); $containerTR.children('td').append($buttonHostDiv); $parentTR.before($containerTR); return; } } const $dynamicForm = $('#dynamic_form'); if ($dynamicForm.length) { $dynamicForm.prepend($buttonHostDiv); } else { const $reportForm = $('form[name="report"]'); if ($reportForm.length) { $reportForm.prepend($buttonHostDiv); } } } // --- Settings Panel Functions (openSettingsPanel, createSettingEntry, closeSettingsPanel) --- // These are unchanged from version 1.3, so they are kept concise here for brevity. // Assume they are correctly implemented as in the previous version. function openSettingsPanel() { /* ... same as v1.3 ... */ $(`#${SETTINGS_MODAL_ID}`).remove(); $('.settings-modal-backdrop').remove(); const backdrop = $('<div class="settings-modal-backdrop"></div>'); $('body').append(backdrop); const modal = $(`<div id="${SETTINGS_MODAL_ID}"></div>`); modal.append('<h3>快捷输入按钮设置</h3>'); const formContainer = $('<div></div>'); buttonsConfig.forEach((btn, index) => { formContainer.append(createSettingEntry(btn, index)); }); modal.append(formContainer); const addButtonRow = $('<button type="button" id="add-button-row">添加新按钮</button>'); addButtonRow.on('click', function() { if (formContainer.children('.button-entry').length < MAX_BUTTONS) { const newIndex = formContainer.children('.button-entry').length; formContainer.append(createSettingEntry({ name: '', text: '' }, newIndex, true)); } else { alert(`最多只能添加 ${MAX_BUTTONS} 个按钮。`); } }); const actions = $('<div class="action-buttons"></div>'); const saveButton = $('<button type="button">保存设置</button>'); saveButton.on('click', function() { const newConfig = []; formContainer.find('.button-entry').each(function() { const name = $(this).find('input[name="btn-name"]').val().trim(); const text = $(this).find('input[name="btn-text"]').val().trim(); if (name && text) { newConfig.push({ name, text }); } }); buttonsConfig = newConfig.slice(0, MAX_BUTTONS); GM_setValue(BUTTON_CONFIG_KEY, buttonsConfig); renderButtons(); closeSettingsPanel(); }); const cancelButton = $('<button type="button" style="background-color: #aaa;">取消</button>'); cancelButton.on('click', closeSettingsPanel); actions.append(addButtonRow).append(saveButton).append(cancelButton); modal.append(actions); $('body').append(modal); backdrop.on('click', closeSettingsPanel); } function createSettingEntry(btn, index, isNew = false) { /* ... same as v1.3 ... */ const entry = $('<div class="button-entry"></div>'); entry.append(`<label style="margin-right:5px;">${index + 1}.</label>`); const nameInput = $(`<input type="text" name="btn-name" placeholder="按钮名称" value="${btn.name}">`); const textInput = $(`<input type="text" name="btn-text" placeholder="快捷文本" value="${btn.text}">`); const removeButton = $('<button type="button" class="remove-btn">移除</button>'); removeButton.on('click', function() { $(this).closest('.button-entry').remove(); $(`#${SETTINGS_MODAL_ID} .button-entry`).each(function(i){ $(this).find('label:first-child').text(`${i+1}.`); }); }); entry.append(nameInput).append(textInput).append(removeButton); if (isNew) nameInput.focus(); return entry; } function closeSettingsPanel() { /* ... same as v1.3 ... */ $(`#${SETTINGS_MODAL_ID}`).remove(); $('.settings-modal-backdrop').remove(); } function initialize() { addGlobalStyles(); GM_registerMenuCommand('设置快捷输入按钮 (DIC Music)', openSettingsPanel, 's'); renderButtons(); const dynamicFormNode = document.getElementById('dynamic_form'); if (dynamicFormNode) { const observer = new MutationObserver(function(mutationsList, observerInstance) { for(let mutation of mutationsList) { if (mutation.type === 'childList') { // Check if children of dynamic_form changed const myTableButtonsExist = $(`#${SCRIPT_BUTTON_TR_ID}`).length > 0; // Check if the div exists and is a direct child of dynamic_form (fallback scenario) const myFallbackButtonsExist = $(`#dynamic_form > #${SCRIPT_BUTTON_CONTAINER_ID}`).length > 0; if (!myTableButtonsExist && !myFallbackButtonsExist) { // This script's buttons are not present in either their primary (table TR) // or fallback (direct child of dynamic_form) locations. const reportFormExists = $('form[name="report"]').length > 0; const dynamicFormStillExists = $('#dynamic_form').length > 0; if (reportFormExists && dynamicFormStillExists) { // console.log("QuickInputHelper: Buttons not found. Attempting to re-render."); renderButtons(); } } break; // Process only one relevant mutation from the list } } }); observer.observe(dynamicFormNode, { childList: true, subtree: true }); } else { let attempts = 0; const interval = setInterval(() => { attempts++; if (document.getElementById('dynamic_form') || attempts > 20) { // Max 10 seconds wait clearInterval(interval); if (document.getElementById('dynamic_form')) { initialize(); // Re-run initialize to attach observer to the now existing form } else { console.warn("QuickInputHelper: #dynamic_form not found after waiting. Buttons may not appear correctly."); } } }, 500); } } $(document).ready(function() { setTimeout(initialize, 750); // Slightly increased delay to allow other scripts potentially more time }); })();