Greasy Fork

来自缓存

Greasy Fork is available in English.

粤语划词翻译

快捷粤语翻译查询

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         粤语划词翻译
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  快捷粤语翻译查询
// @author       口吃者
// @match        http://*/*
// @include      https://*/*
// @include      file:///*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=shyyp.net
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM.setValue
// @grant        GM.getValue
// @grant        GM_registerMenuCommand
// @require      https://update.greasyfork.icu/scripts/498507/1398070/sweetalert2.js
// @license MIT
// ==/UserScript==
const shyypTokenUrl = 'https://shyyp.net/api/gqgq2';
const shyypLongScriptUrl = 'https://shyyp.net/romanizer';//长文注音
const shyypConvertUrl = 'https://shyyp.net/translator';//粤普转换
const shyypSingleWorldUrl = 'https://shyyp.net/w/';
const shyypIconUrl = 'https://img.picui.cn/free/2024/10/25/671b96c09fe69.png'
const shyypIconMosaicUrl = 'https://img.picui.cn/free/2024/10/25/671b96c14d5cc.png'
const shyypIconOnlyHeadUrl = 'https://img.picui.cn/free/2024/10/25/671b96c1c28f3.png'
const yueyuemaoSingleWordUrl = 'https://www.yueyumao.com/detail/';
const yueyuemaoPhraseUrl = 'https://www.yueyumao.com/search.php?q=';
const yueyuemaoLongScriptUrl = 'https://www.yueyumao.com/';
const yueyuemaoIconCat01 = 'https://img.picui.cn/free/2024/10/26/671cb240d0071.png';
const yueyuemaoIconCat02 = 'https://img.picui.cn/free/2024/10/26/671cb240cf59a.png';
const yueyuemaoIconCat03 = 'https://img.picui.cn/free/2024/10/26/671cb240c851a.png';
const moreIconUrl = 'https://img.picui.cn/free/2024/10/26/671c6876ed78d.png';
let textEncry = '';
let selected;// 当前选中文本
let pageX;// 图标显示的 X 坐标
let pageY;// 图标显示的 Y 坐标
const dragFluctuation = 4;// 当拖动多少像素以上时不触发查询
const zIndex = '2147473647'; // 渲染图层
/**鼠标拖动*/
class Drag {
    constructor(element) {
        this.dragging = false;
        this.startDragTime = 0;
        this.stopDragTime = 0;
        this.mouseDownPositionX = 0;
        this.mouseDownPositionY = 0;
        this.elementOriginalLeft = parseInt(element.style.left);
        this.elementOriginalTop = parseInt(element.style.top);
        this.backAndForthLeftMax = 0;
        this.backAndForthTopMax = 0;
        this.element = element;

        // 绑定事件处理函数
        // 事件处理函数由dom元素调用,一般是指向dom元素,强制绑定到Drag类上
        this.startDrag = this.startDrag.bind(this);
        this.dragElement = this.dragElement.bind(this);
        this.stopDrag = this.stopDrag.bind(this);

        // 添加鼠标事件监听器
        this.attachEventListeners();
    }

    attachEventListeners() {
        this.element.addEventListener('mousedown', this.startDrag);
    }

    detachEventListeners() {
        window.removeEventListener('mousemove', this.dragElement);
        window.removeEventListener('mouseup', this.stopDrag);
    }

    startDrag(e) {
        //阻止默认鼠标事件,比如选中文字
        e.preventDefault();
        this.dragging = true;
        this.startDragTime = new Date().getTime();
        this.mouseDownPositionX = e.clientX;
        this.mouseDownPositionY = e.clientY;
        this.elementOriginalLeft = parseInt(this.element.style.left);
        this.elementOriginalTop = parseInt(this.element.style.top);
        this.backAndForthLeftMax = 0;
        this.backAndForthTopMax = 0;

        // 设置全局鼠标事件
        window.addEventListener('mousemove', this.dragElement);
        window.addEventListener('mouseup', this.stopDrag);
        log('startDrag');
    }

    stopDrag(e) {
        e.preventDefault();
        this.dragging = false;
        this.stopDragTime = new Date().getTime();
        this.detachEventListeners();
        log('stopDrag');
    }

    dragElement(e) {
        log('dragging');
        if (!this.dragging) {
            return;
        }
        e.preventDefault();

        // 移动元素
        this.element.style.left = `${this.elementOriginalLeft + (e.clientX - this.mouseDownPositionX)}px`;
        this.element.style.top = `${this.elementOriginalTop + (e.clientY - this.mouseDownPositionY)}px`;

        // 获取最大移动距离
        let left = Math.abs(this.elementOriginalLeft - parseInt(this.element.style.left));
        let top = Math.abs(this.elementOriginalTop - parseInt(this.element.style.top));

        //更新最大移动距离
        if (left > this.backAndForthLeftMax) {
            this.backAndForthLeftMax = left;
        }
        if (top > this.backAndForthTopMax) {
            this.backAndForthTopMax = top;
        }
        log('dragElement');
    }
}
(function() {
    'use strict';
    const icon = document.createElement('tr-icon');// 翻译图标
    icon.id = 'cantonese_translate';
    icon.style.cssText = 'display: none;top: 186px;left: 37px;position: absolute;z-index: 2147473647;cursor:move;';
    const imgShyyp = getImg(shyypIconUrl, 'shyyp', '羊羊粤语-长文注音');
    const imgShyyp01 = getImg(shyypIconMosaicUrl, 'shyyp01', '羊羊粤语-单字查询');
    const imgShyyp02 = getImg(shyypIconOnlyHeadUrl, 'shyyp03', '羊羊粤语-粤普转换');
    const imgYueyuemao = getImg(yueyuemaoIconCat01, 'yueyuemao', '粤语猫-长文注音');
    const imgYueyuemao01 = getImg(yueyuemaoIconCat02, 'yueyuemao01', '粤语猫-单字查询');
    const imgYueyuemao02 = getImg(yueyuemaoIconCat03, 'yueyuemao02', '粤语猫-关联词组');
    const ifMore = getImg(moreIconUrl, 'more', '更多-折叠其后功能)');
    const iconsArray = [
        {id:1, iconEle: imgShyyp, name: imgShyyp.getAttribute('title'), mouseupFuc: longscriptPopup}, 
        {id:2, iconEle: imgShyyp01, name: imgShyyp01.getAttribute('title'), mouseupFuc: singleWorldPopup},
        {id:3, iconEle: imgShyyp02, name: imgShyyp02.getAttribute('title'), mouseupFuc: toMandarionOrCantonese}, 
        {id:7, iconEle: ifMore, name: ifMore.getAttribute('title'), mouseupFuc: showMore},
        {id:4, iconEle: imgYueyuemao, name: imgYueyuemao.getAttribute('title'), mouseupFuc: longscriptQueryYueYueMao}, 
        {id:5, iconEle: imgYueyuemao01, name: imgYueyuemao01.getAttribute('title'), mouseupFuc: singleWordQueryYueYueMao}, 
        {id:6, iconEle: imgYueyuemao02, name: imgYueyuemao02.getAttribute('title'), mouseupFuc: phraseCorrelationYueYueMao}
    ];
    const sortOrder = GM_getValue('sortOrder', iconsArray.map(icon => icon.id));
    const hideConfig = GM_getValue('hideConfig', {});
    const customIcons = getCustomMadeIconArray(sortOrder);
    let isIconImgMore = false;
    customIcons.forEach(iconCustom => {
        const iconEleNew = iconCustom.iconEle;
        iconEleNew.addEventListener('mouseup', iconCustom.mouseupFuc);
        if (isIconImgMore) {
            iconEleNew.setAttribute('is-more', 'true');
        }
        if (iconCustom.id === 7) {
            isIconImgMore = true;
        }
        if (!hideConfig[iconCustom.id]) {
            icon.appendChild(iconEleNew);
        }
    });

    // 绑定图标拖动事件
    const iconDrag = new Drag(icon);
    //区分拖动和点击事件,有足够位移才触发窗口事件
    document.body.appendChild(icon);
    // 鼠标事件:防止选中的文本消失;显示、隐藏翻译图标
    document.addEventListener('mouseup', showIcon);
    // 选中变化事件
    document.addEventListener('selectionchange', showIcon);
    document.addEventListener('touchend', showIcon);
    //粤普转换自动化操作
    window.onload = () =>{
        checkUrlAndExecute(async function auto() {
            selected = await GM.getValue('selectedText', '');
            await new Promise(resolve => setTimeout(resolve, 200));
            var textareaEle = document.querySelector("#stage0");
            textareaEle.value = selected;
        } ,shyypConvertUrl)
        checkUrlAndExecute(async function auto() {
            selected = await GM.getValue('selectedText', '');
            await new Promise(resolve => setTimeout(resolve, 200));
            var textareaEle = document.querySelector("#hanzi_string");
            textareaEle.value = selected;
            await new Promise(resolve => setTimeout(resolve, 200));
            var butttonSubmit = document.querySelector("#form_1 button");
            butttonSubmit.click();
        } ,yueyuemaoLongScriptUrl)
    }
    const listItems = customIcons.map((icon, index) => (
        `
        <li data-index="${index}" draggable="true">
            ${icon.name}
            <input data-id="${icon.id}" type="checkbox" ${hideConfig[icon.id] ? '' : 'checked'}>
        </li>`
    )).join('');
    GM_registerMenuCommand("功能定制化", function() {
        Swal.fire({
            title: '个性化',
            html: `
                <div id="swIconDiv" style="max-height: 300px; overflow: auto;">
                    <ul id="iconList" style="list-style-type:none; margin:0; padding:20px;">
                        ${listItems}
                    </ul>
                </div>
                <p style="font-size: small;color: #A7A7A7">拖动调整顺序,确认后刷新生效</p>
                `,
            showCancelButton: true,
            showDenyButton: true,
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            denyButtonText: `重置`,
            didOpen: () => {
                // 在弹窗完全打开后初始化拖放功能
                const iconList = document.getElementById('iconList');

                iconList.addEventListener('dragstart', dragStartHandler);
                iconList.addEventListener('drop', dropHandler);
                iconList.addEventListener('dragover', dragOverHandler);

                // 在拖动结束时移除样式
                iconList.addEventListener('dragend', dragEndHandler);

                // 设置可拖动属性
                Array.from(iconList.children).forEach(item => {
                    item.draggable = true;
                });
            },
            willClose: () => {
                // 在关闭前清除事件监听器以防止内存泄漏
                const iconList = document.getElementById('iconList');
                iconList.removeEventListener('dragstart', dragStartHandler);
                iconList.removeEventListener('drop', dropHandler);
                iconList.removeEventListener('dragover', dragOverHandler);
                iconList.removeEventListener('dragend', dragEndHandler);
            },
            preConfirm: () => {
                document.querySelectorAll('#iconList input').forEach(hideInput => {
                    if (!hideInput.checked) {
                        hideConfig[parseInt(hideInput.getAttribute('data-id'))] = true;
                    }else {
                        delete hideConfig[parseInt(hideInput.getAttribute('data-id'))];
                    }
                });
                GM_setValue('hideConfig', hideConfig);
                return {
                    updatedIcons: customIcons.slice() // 返回修改后的图标数组副本
                };
            }
        }).then((result) => {
            if (result.isConfirmed) {
                const ids = result.value.updatedIcons.map(({id}) => id);
                GM_setValue('sortOrder', ids);
                console.log(result.value.updatedIcons); // 打印调整后的图标顺序
            } else if (result.isDenied) {
                GM_setValue('sortOrder', iconsArray.map(icon => icon.id));
                GM_setValue('hideConfig', {});
            }
        });
    });


    var cssText = `
        #cantonese_translate img:hover{
            cursor:pointer;
        }
        #cantonese_translate img:hover{
            border:1px solid #1ABB27
        }
        #cantonese_translate img{
            cursor:pointer;
            display:inline-block;
            width:20px;
            height:20px;
            border:1px solid #dfe1e5;
            border-radius:4px;
            background-color:rgba(255,255,255,1);
            padding:2px;
            margin:0;
            margin-right:5px;
            box-sizing:content-box;vertical-align:middle
        }
        #iconList li:hover{
            cursor:pointer;
            border:1px solid #1ABB27;
        }
        #swIconDiv + p:hover{
            background-color: lightgoldenrodyellow;
            font-weight:bold;
        }
    `
    GMaddStyle(cssText);
    /*  获取长文注音路径参数x请求的json*/
    function createMutationJson(srcValue) {
        const queryTemplate = `mutation Submit($src: String!){ submitSrc(src: $src) }`;
        const variables = { src: srcValue };
        const query = `{"query":"${queryTemplate}","variables":${JSON.stringify(variables)}}`;
        return JSON.parse(query);
    }
    async function sendPostRequest(url, data) {
        const body = JSON.stringify(data);
        const headers = new Headers({
            'Content-Type': 'application/json'
        });
        const options = {
            method: 'POST',
            headers,
            body
        };
        try {
            const response = await fetch(url, options);
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        } catch (error) {
            console.error('Failed to fetch:', error);
        }
    }
    function sendPostRequestWithGM(url, data) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'POST',
                url: url,
                data: JSON.stringify(data),
                headers: {
                    'Content-Type': 'application/json'
                },
                onload: function(response) {
                    resolve(JSON.parse(response.responseText));
                },
                onerror: function(error) {
                    reject(error);
                }
            });
        });
    }
    /* 长文获取整页html,目前不需要 */
    async function sendGetRequestHtml(urlBase, param) {
        const url = new URL(urlBase);
        url.searchParams.set('x', param);
        try {
            const response = await fetch(url);
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            const htmlContent = await response.text();
            return htmlContent;
        } catch (error) {
            console.error('Failed to fetch:', error);
        }
    }
    function getImg(src01, alt01, title01, options = {}) {
        // 创建一个新的 img 元素
        const img = document.createElement('img');
        // 设置 img 元素的基本属性
        img.src = src01;
        img.alt = alt01;
        img.title = title01;
        // 设置额外的属性
        if (options.width) {
            img.width = options.width;
        }
        if (options.height) {
            img.height = options.height;
        }
        if (options.className) {
            img.className = options.className;
        }
        if (options.style) {
            Object.keys(options.style).forEach(key => {
                img.style[key] = options.style[key];
            });
        }
        // 返回创建的 img 元素
        return img;
    }
    /** 弹出居中窗口 */
    function popupCenter(url, title = '_blank', w, h) {
        // 检查参数有效性
        if (!url || typeof url !== 'string') {
            console.error('Invalid URL provided');
            return null;
        }

        // 设置默认标题和窗口尺寸
        title = title || '_blank';
        w = Math.min(w, screen.availWidth);
        h = Math.min(h, screen.availHeight);

        // 计算居中位置
        let x = (screen.availWidth - w) / 2;
        let y = (screen.availHeight - h) / 2;

        // 确保窗口不会超出屏幕边界
        x = Math.max(x, 0);
        y = Math.max(y, 0);

        // 打开新窗口
        let win;
        try {
            win = window.open(url, title, `width=${w},height=${h},left=${x},top=${y}`);
            if (win) {
                win.focus();
                let closeNewWindow =  window.addEventListener('focus', function() {
                    win.close();
                    window.removeEventListener('focus', closeNewWindow);
                });
            } else {
                throw new Error('Failed to open the window');
            }
        } catch (e) {
            console.error('Error opening the window:', e);
        }

        return win;
    }
    /**显示 icon*/
    function showIcon(e) {
        log('showIcon event:', e);
        let offsetX = -100; // 横坐标翻译图标偏移
        let offsetY = -40; // 纵坐标翻译图标偏移
        // 更新翻译图标 X、Y 坐标
        if (e.pageX && e.pageY) { // 鼠标
            log('mouse pageX/Y');
            pageX = e.pageX;
            pageY = e.pageY;
        }
        if (e.changedTouches) { // 触屏
            if (e.changedTouches.length > 0) { // 多点触控选取第 1 个
                log('touch pageX/Y');
                pageX = e.changedTouches[0].pageX;
                pageY = e.changedTouches[0].pageY;
                // 触屏修改翻译图标偏移(Android、iOS 选中后的动作菜单一般在当前文字顶部,翻译图标则放到底部)
                offsetX = -26; // 单个翻译图标块宽度
                offsetY = 16 * 3; // 一般字体高度的 3 倍,距离系统自带动作菜单、选择光标太近会导致无法点按
            }
        }
        log(`selected:${selected}, pageX:${pageX}, pageY:${pageY}`)
        if (e.target == icon || (e.target.parentNode && e.target.parentNode == icon)) { // 点击了翻译图标
            e.preventDefault();
            return;
        }
        selected = window.getSelection().toString().trim(); // 当前选中文本
        GM_setValue('selectedText', selected);
        log(`selected:${selected}, icon display:${icon.style.display}`);
        if (selected && icon.style.display != 'block' && pageX && pageY) { // 显示翻译图标
            log('show icon');
            icon.style.top = `${pageY + offsetY}px`;
            icon.style.left = `${pageX + offsetX}px`;
            icon.style.display = 'block';
            // 兼容部分 Content Security Policy
            icon.style.position = 'absolute';
            icon.style.zIndex = zIndex;
        } else if (!selected) { // 隐藏翻译图标
            log('hide icon');
            hideIcon();
        }
    }
    /**隐藏 icon*/
    function hideIcon() {
        icon.style.display = 'none';
        pageX = 0;
        pageY = 0;
        icon.querySelectorAll('img[is-more]').forEach(ele => {
            ele.style.display = 'none';
        });
    }
    /* 长文注音弹出 */
    async function longscriptPopup(){
        try {
            const response = await sendPostRequestWithGM(shyypTokenUrl, createMutationJson(selected));
            textEncry = response.data.submitSrc;
            console.log(textEncry);
            await new Promise(resolve => setTimeout(resolve, 100));
            if (iconDrag.backAndForthLeftMax <= dragFluctuation && iconDrag.backAndForthTopMax <= dragFluctuation) {
                popupCenter(`${shyypLongScriptUrl}?x=${textEncry}`, '长文注音', 1024, 800);
            }
        } catch (error) {
            console.error('Error:', error);
        }
    }
    /* 单字弹出 */
    async function singleWorldPopup(){
        try {
            await new Promise(resolve => setTimeout(resolve, 100));
            if (iconDrag.backAndForthLeftMax <= dragFluctuation && iconDrag.backAndForthTopMax <= dragFluctuation) {
                popupCenter(`${shyypSingleWorldUrl}${selected}`, '单字查询', 1024, 800);
            }
        } catch (error) {
            console.error('Error:', error);
        }
    }
    /* 粤普转换弹出 */
    async function toMandarionOrCantonese(){
        try {
            await new Promise(resolve => setTimeout(resolve, 100));
            if (iconDrag.backAndForthLeftMax <= dragFluctuation && iconDrag.backAndForthTopMax <= dragFluctuation) {
                popupCenter(shyypConvertUrl, '粤普转换', 1024, 800);
            }
        } catch (error) {
            console.error('Error:', error);
        }
    }
    /* 粤粤猫 单字查询 */
    async function singleWordQueryYueYueMao(){
        try {
            await new Promise(resolve => setTimeout(resolve, 100));
            if (iconDrag.backAndForthLeftMax <= dragFluctuation && iconDrag.backAndForthTopMax <= dragFluctuation) {
                popupCenter(`${yueyuemaoSingleWordUrl}${selected}.html`, '单字查询', 1024, 800);
            }
        } catch(error) {}
    }
    /* 粤粤猫 长文注音 */
    async function longscriptQueryYueYueMao(){
        try {
            await new Promise(resolve => setTimeout(resolve, 100));
            if (iconDrag.backAndForthLeftMax <= dragFluctuation && iconDrag.backAndForthTopMax <= dragFluctuation) {
                popupCenter(yueyuemaoLongScriptUrl, '长文注音', 1024, 800);
            }
        } catch(error) {}
    }

    /* 粤粤猫 关联词组 */
    async function phraseCorrelationYueYueMao(){
        try {
            await new Promise(resolve => setTimeout(resolve, 100));
            if (iconDrag.backAndForthLeftMax <= dragFluctuation && iconDrag.backAndForthTopMax <= dragFluctuation) {
                popupCenter(`${yueyuemaoPhraseUrl}${selected}`, '长文注音', 1024, 800);
            }
        } catch(error) {}
    }
    /* 新窗口自动化操作 */
    function checkUrlAndExecute(customFunction, targetUrl) {
        // 获取当前页面的完整URL
        const currentUrl = window.location.href;
        
        // 检查当前URL是否与目标URL相等
        if (currentUrl === targetUrl) {
            // 如果URL匹配,则执行自定义函数
            customFunction();
        }
    }
    /* 返回定制化顺序的图标数组 */
    function getCustomMadeIconArray(defaultOrder) {
        // 根据 defaultOrder 排序图标数组
        console.log(defaultOrder)
        //排序逻辑是通过比较 a 和 b 的 id 在 defaultOrder 数组中的索引来决定的,与id大小无关
        const sortedIcons = iconsArray.filter(icon => defaultOrder.includes(icon.id))
                                 .sort((a, b) => defaultOrder.indexOf(a.id) - defaultOrder.indexOf(b.id));
        return sortedIcons;
    }
    /* 更多 */
    function showMore() {
        icon.querySelectorAll('img[is-more]').forEach(ele => {
            if (ele.style.display == 'inline-block') {
                ele.style.display = 'none';
            } else {
                ele.style.display = 'inline-block';
            }
        });
    }
    function arrayMove(arr, fromIndex, toIndex) {
        const element = arr[fromIndex];
        arr.splice(fromIndex, 1);
        arr.splice(toIndex, 0, element);
        return arr;
    }
/*     function setupIconList() {
        const sortOrder = GM_getValue('sortOrder', iconsArray.map(icon => icon.id));
        const hideConfig = GM_getValue('hideConfig', {});

        const icons = getCustomMadeIconArray(sortOrder);

        // 清空现有的图标列表
        document.querySelectorAll('.icon-item').forEach(ele => ele.remove());

        // 重新渲染图标列表
        icons.forEach((icon, index) => {
            const iconItem = document.createElement('div');
            iconItem.className = 'icon-item';

            const upButton = document.createElement('button');
            upButton.textContent = '⬆️';
            upButton.onclick = function() {
                if (index > 0) {
                    const newIcons = arrayMove(icons, index, index - 1);
                    const newSortOrder = newIcons.map(i => i.id);
                    GM_setValue('sortOrder', newSortOrder);
                    setupIconList(); // 重新设置图标列表
                }
            };

            const downButton = document.createElement('button');
            downButton.textContent = '⬇️';
            downButton.onclick = function() {
                if (index < icons.length - 1) {
                    const newIcons = arrayMove(icons, index, index + 1);
                    const newSortOrder = newIcons.map(i => i.id);
                    GM_setValue('sortOrder', newSortOrder);
                    setupIconList(); // 重新设置图标列表
                }
            };

            const toggleVisibilityButton = document.createElement('button');
            toggleVisibilityButton.textContent = hideConfig[icon.id] ? '显示' : '隐藏';
            toggleVisibilityButton.onclick = function() {
                if (toggleVisibilityButton.textContent === '隐藏') {
                    hideConfig[icon.id] = true;
                    toggleVisibilityButton.textContent = '显示';
                } else {
                    delete hideConfig[icon.id];
                    toggleVisibilityButton.textContent = '隐藏';
                }
                GM_setValue('hideConfig', hideConfig);
                setupIconList(); // 重新设置图标列表
            };

            const iconLabel = document.createElement('span');
            iconLabel.className = 'icon-name';
            iconLabel.textContent = icon.name;

            iconItem.appendChild(upButton);
            iconItem.appendChild(downButton);
            iconItem.appendChild(toggleVisibilityButton);
            iconItem.appendChild(iconLabel);

            document.body.appendChild(iconItem);
        });
    } */
    function swapIcons(index1, index2) {
        // 获取图标列表
        if(index1 === index2){
            return;
        }
        if(index1 > index2){
            swapIcons(index2, index1);
            return;
        }
        const iconList = document.getElementById('iconList');
        // 根据data-index获取图标元素
        const icon1 = iconList.querySelector(`[data-index="${index1}"]`);
        const icon2 = iconList.querySelector(`[data-index="${index2}"]`);
        if (!icon1 || !icon2) {
            console.error('Invalid index provided.');
            return;
        }
        // 获取两个图标在父节点中的位置
        const parent = icon1.parentNode;
/*             const index1Pos = Array.from(parent.children).indexOf(icon1);
        const index2Pos = Array.from(parent.children).indexOf(icon2); */
        let tempIcon1Next = icon1.nextSibling;
        // 交换它们的位置
        parent.insertBefore(icon1, icon2.nextSibling);
        parent.insertBefore(icon2, tempIcon1Next);

    }
    // 初始化拖放功能
    const dragStartHandler = function(e) {
        e.dataTransfer.setData('text/plain', e.target.dataset.index);
    };

    const dropHandler = function(e) {
        e.preventDefault(); // 阻止默认行为

        // 获取当前拖动元素的新位置
        const newIndex = e.target.closest('li') ? e.target.closest('li').dataset.index : e.target.children.length - 1;
        const oldIndexStr = e.dataTransfer.getData('text/plain');
        const oldIndex = parseInt(oldIndexStr);

        if (newIndex === oldIndex) return;

        // 更新 DOM 中的列表项
        const itemToMove = this.querySelector(`li[data-index="${oldIndex}"]`);

        // 确保在正确的位置插入或移除元素
        swapIcons(newIndex, oldIndex);

        // 更新 icons 数组中的顺序
        const temp = customIcons[newIndex];
        customIcons[newIndex] = customIcons[oldIndex];
        customIcons[oldIndex] = temp;

        // 更新列表项的 data-index 属性
        for (let i = 0; i < customIcons.length; i++) {
            const listItem = this.querySelector(`#iconList :nth-child(${i+1})`);
            listItem.dataset.index = i.toString();
        }
    };

    const dragOverHandler = function(e) { 
        e.preventDefault(); 
        e.currentTarget.classList.add('drag-over');
    };

    const dragEndHandler = function(e) { 
        e.currentTarget.classList.remove('drag-over');
    };
})();
/**日志输出*/
function log(...args) {
    const debug = false;
    if (!debug) {
        return;
    }
    if (args) {
        for (let i = 0; i < args.length; i++) {
            console.log(args[i]);
        }
    }
}
function GMaddStyle(css){
    var myStyle = document.createElement('style');
    myStyle.textContent = css;
    var doc = document.head || document.documentElement;
    doc.appendChild(myStyle);
}