Greasy Fork

Greasy Fork is available in English.

link工具

点击复制,提取链接

目前为 2024-06-22 提交的版本,查看 最新版本

// ==UserScript==
// @name         link工具
// @namespace    http://tampermonkey.net/
// @version      0.4.5
// @description  点击复制,提取链接
// @author       lwj
// @match        https://*
// @license      MIT
// @grant        GM_setClipboard
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    // 检查当前页面 URL 是否匹配指定的网址
    var isHomeURL = function() {
        return window.location.href.indexOf("https://m.linkmcn.com/#/live/plan?select=") !== -1;
    };

    var isTableCardURL = function() {
        return window.location.href.indexOf("https://m.linkmcn.com/#/live/plan/tableCard/") !== -1;
    };

    // 初始化开关状态
    var copySwitchState = localStorage.getItem('copySwitchState') === 'true';
    var toggleSwitchState = localStorage.getItem('toggleSwitchState') === 'true';
    var onlyItemIdSwitchState = localStorage.getItem('onlyItemIdSwitchState') === 'true';
    var tableCardPngSwitchState = localStorage.getItem('tableCardPngSwitchState') === 'true';

    var notificationTimer; // 通知计时器
    let clipboardText = ""; // 剪切板

    // 创建开关容器元素
    var switchesContainer = document.createElement('div');
    switchesContainer.classList.add('flex', 'items-center', 'justify-between', 'pb-12');
    switchesContainer.style.cssText = 'position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 9999;';
    if (isHomeURL()) {
        document.body.appendChild(switchesContainer);
    }

    // 创建点击复制开关元素
    var copySwitchContainer = document.createElement('div');
    copySwitchContainer.classList.add('flex', 'items-center');

    var copySwitchText = document.createElement('span');
    copySwitchText.textContent = '点击店名复制';
    copySwitchText.classList.add('mr-8', 'ml-4', 'lh-22');
    copySwitchContainer.appendChild(copySwitchText);

    var copySwitch = document.createElement('button');
    copySwitch.innerHTML = '<div class="ant-switch-handle"></div><span class="ant-switch-inner"><span class="ant-switch-inner-checked"></span><span class="ant-switch-inner-unchecked"></span></span>';
    copySwitch.setAttribute('type', 'button');
    copySwitch.setAttribute('role', 'switch');
    copySwitch.setAttribute('aria-checked', copySwitchState); // 设置开关状态
    copySwitch.classList.add('ant-switch', 'css-9fw9up');
    if (copySwitchState) {
        copySwitch.classList.add('ant-switch-checked'); // 开启
    }
    copySwitchContainer.appendChild(copySwitch);

    switchesContainer.appendChild(copySwitchContainer);

    // 创建下拉菜单容器
    var dropdownContainer = document.createElement('div');
    dropdownContainer.style.cssText = 'position: relative; display: inline-block;';

    var dropdownButton = document.createElement('button');
    dropdownButton.textContent = '更多功能';
    dropdownButton.style.cssText = 'margin-left: 20px; padding: 5px 10px; cursor: pointer;border-radius: 999px;';
    dropdownButton.classList.add('ant-btn','css-9fw9up', 'ant-btn-default', 'primaryButton___N3z1x');
    dropdownContainer.appendChild(dropdownButton);

    // 创建下拉菜单内容
    var dropdownContent = document.createElement('div');
    dropdownContent.style.cssText = 'display: none; position: absolute; background-color: #f9f9f9; min-width: 200px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1;border-radius: 10px;';

    // 创建快捷粘贴搜索开关元素
    var toggleSwitchContainer = document.createElement('div');
    toggleSwitchContainer.classList.add('flex', 'items-center', 'dropdown-item');
    toggleSwitchContainer.style.cssText = 'padding: 12px 16px; cursor: pointer; display: flex; justify-content: space-between;';

    var toggleSwitchText = document.createElement('span');
    toggleSwitchText.textContent = '快捷粘贴搜索';
    toggleSwitchText.classList.add('lh-22');
    toggleSwitchContainer.appendChild(toggleSwitchText);

    var toggleSwitch = document.createElement('button');
    toggleSwitch.innerHTML = '<div class="ant-switch-handle"></div><span class="ant-switch-inner"><span class="ant-switch-inner-checked"></span><span class="ant-switch-inner-unchecked"></span></span>';
    toggleSwitch.setAttribute('type', 'button');
    toggleSwitch.setAttribute('role', 'switch');
    toggleSwitch.setAttribute('aria-checked', toggleSwitchState); // 设置开关状态
    toggleSwitch.classList.add('ant-switch', 'css-9fw9up');
    if (toggleSwitchState) {
        toggleSwitch.classList.add('ant-switch-checked');
    }
    toggleSwitchContainer.appendChild(toggleSwitch);

    // 创建提取商品链接开关元素
    var onlyItemIdSwitchContainer = document.createElement('div');
    onlyItemIdSwitchContainer.classList.add('flex', 'items-center', 'dropdown-item');
    onlyItemIdSwitchContainer.style.cssText = 'padding: 12px 16px; cursor: pointer; display: flex; justify-content: space-between;';

    var onlyItemIdSwitchText = document.createElement('span');
    onlyItemIdSwitchText.textContent = '提取商品链接';
    onlyItemIdSwitchText.classList.add('lh-22');
    onlyItemIdSwitchContainer.appendChild(onlyItemIdSwitchText);

    var onlyItemIdSwitch = document.createElement('button');
    onlyItemIdSwitch.innerHTML = '<div class="ant-switch-handle"></div><span class="ant-switch-inner"><span class="ant-switch-inner-checked"></span><span class="ant-switch-inner-unchecked"></span></span>';
    onlyItemIdSwitch.setAttribute('type', 'button');
    onlyItemIdSwitch.setAttribute('role', 'switch');
    onlyItemIdSwitch.setAttribute('aria-checked', onlyItemIdSwitchState); // 设置开关状态
    onlyItemIdSwitch.classList.add('ant-switch', 'css-9fw9up');
    if (onlyItemIdSwitchState) {
        onlyItemIdSwitch.classList.add('ant-switch-checked');
    }
    onlyItemIdSwitchContainer.appendChild(onlyItemIdSwitch);

    // 创建手卡快捷截图开关元素
    var tableCardPngSwitchContainer = document.createElement('div');
    tableCardPngSwitchContainer.classList.add('flex', 'items-center', 'dropdown-item');
    tableCardPngSwitchContainer.style.cssText = 'padding: 12px 16px; cursor: pointer; display: flex; justify-content: space-between;';

    var tableCardPngSwitchText = document.createElement('span');
    tableCardPngSwitchText.textContent = '手卡快捷截图';
    tableCardPngSwitchText.classList.add('lh-22');
    tableCardPngSwitchContainer.appendChild(tableCardPngSwitchText);

    var tableCardPngSwitch = document.createElement('button');
    tableCardPngSwitch.innerHTML = '<div class="ant-switch-handle"></div><span class="ant-switch-inner"><span class="ant-switch-inner-checked"></span><span class="ant-switch-inner-unchecked"></span></span>';
    tableCardPngSwitch.setAttribute('type', 'button');
    tableCardPngSwitch.setAttribute('role', 'switch');
    tableCardPngSwitch.setAttribute('aria-checked', tableCardPngSwitchState); // 设置开关状态
    tableCardPngSwitch.classList.add('ant-switch', 'css-9fw9up');
    if (tableCardPngSwitchState) {
        tableCardPngSwitch.classList.add('ant-switch-checked');
    }
    tableCardPngSwitchContainer.appendChild(tableCardPngSwitch);

    dropdownContent.appendChild(toggleSwitchContainer);
    dropdownContent.appendChild(onlyItemIdSwitchContainer);
    // dropdownContent.appendChild(tableCardPngSwitchContainer);
    dropdownContainer.appendChild(dropdownContent);
    switchesContainer.appendChild(dropdownContainer);

    // 下拉按钮点击事件
    dropdownButton.addEventListener('click', function() {
        dropdownContent.style.display = dropdownContent.style.display === 'none' ? 'block' : 'none';
    });

    // 点击外部区域隐藏下拉菜单
    window.addEventListener('click', function(event) {
        if (!dropdownContainer.contains(event.target)) {
            dropdownContent.style.display = 'none';
        }
    });

    // 创建通知弹窗
    var NotificationContainer = document.createElement('div');
    NotificationContainer.style.cssText = 'position: fixed; bottom: 60px; left: 50%; transform: translateX(-50%); background-color: rgba(0, 0, 0, 0.5); color: #fff; padding: 10px; border-radius: 10px; display: none; z-index: 9999;';
    document.body.appendChild(NotificationContainer);

    // 获取开关元素
    var copySwitchHandle = copySwitch.querySelector('.ant-switch-handle');
    var toggleSwitchHandle = toggleSwitch.querySelector('.ant-switch-handle');
    var onlyItemIdSwitchHandle = onlyItemIdSwitch.querySelector('.ant-switch-handle');
    var tableCardPngSwitchHandle = tableCardPngSwitch.querySelector('.ant-switch-handle');

    // 更新本地存储的开关状态
    var updateSwitchState = function(switchName, newState) {
        localStorage.setItem(switchName, newState.toString());
    };

    // 监听开关点击事件
    copySwitch.addEventListener('click', function() {
        var newState = copySwitch.getAttribute('aria-checked') === 'true' ? false : true;
        copySwitch.setAttribute('aria-checked', newState);
        if (newState) {
            copySwitch.classList.add('ant-switch-checked');
        } else {
            copySwitch.classList.remove('ant-switch-checked');
        }
        updateSwitchState('copySwitchState', newState);
    });

    toggleSwitch.addEventListener('click', function() {
        var newState = toggleSwitch.getAttribute('aria-checked') === 'true' ? false : true;
        toggleSwitch.setAttribute('aria-checked', newState);
        if (newState) {
            toggleSwitch.classList.add('ant-switch-checked');
        } else {
            toggleSwitch.classList.remove('ant-switch-checked');
        }
        updateSwitchState('toggleSwitchState', newState);
    });

    // 手卡快捷截图开关点击事件
    tableCardPngSwitch.addEventListener('click', function() {
        var newState = tableCardPngSwitch.getAttribute('aria-checked') === 'true' ? false : true;
        tableCardPngSwitch.setAttribute('aria-checked', newState);
        if (newState) {
            tableCardPngSwitch.classList.add('ant-switch-checked');
        } else {
            tableCardPngSwitch.classList.remove('ant-switch-checked');
        }
        updateSwitchState('tableCardPngSwitchState', newState);
    });

    // 提取商品链接开关点击事件
    onlyItemIdSwitch.addEventListener('click', function() {
        var newState = onlyItemIdSwitch.getAttribute('aria-checked') === 'true' ? false : true;
        onlyItemIdSwitch.setAttribute('aria-checked', newState);
        if (newState) {
            onlyItemIdSwitch.classList.add('ant-switch-checked');
        } else {
            onlyItemIdSwitch.classList.remove('ant-switch-checked');
        }
        updateSwitchState('onlyItemIdSwitchState', newState);
    });

    // 单击和双击事件的延迟和计数器
    var delay = 200; // 延迟时间,单位毫秒
    var clicks = 0;
    var timer = null;

    // 监听鼠标左键点击事件
    document.addEventListener('click', function(event) {
        // 检查是否开启了点击复制功能且在匹配的网址上
        if (copySwitch.getAttribute('aria-checked') === 'true' && isHomeURL()) {
            clicks++;
            if (clicks % 2 === 1) {
                timer = setTimeout(function() {
                    // 单击操作
                    clicks = 0;
                    handleSingleClick(event);
                }, delay);
            } else {
                // 取消之前的单击操作
                clearTimeout(timer);
                clicks = 0;
                handleDoubleClick(event);
            }
        }
    });

    // 单击处理函数
    function handleSingleClick(event) {
        if (event.target && event.target.classList.contains('link-overflow-tip')) {
            var text = event.target.textContent;
            var copiedText = text.substring();
            GM_setClipboard(copiedText);
            showNotification("复制成功:"+copiedText);
        }
    }

    // 双击处理函数
    function handleDoubleClick(event) {
        if (event.target && event.target.classList.contains('link-overflow-tip')) {
            var text = event.target.textContent;
            var copiedText = text.substring(0, 3);
            GM_setClipboard(copiedText);
            showNotification("复制成功:"+copiedText);
        }
    }

    // 显示通知
    function showNotification(message, showImage = false) {
        NotificationContainer.textContent = message;
        NotificationContainer.style.display = 'inline-block'; // 设置为 inline-block
        NotificationContainer.style.textAlign = 'center'; // 让文本居中显示
        NotificationContainer.style.width = 'auto'; // 设置宽度自动调整
        NotificationContainer.style.padding = '10px'; // 设置内边距

        // 清除之前的计时器
        if (notificationTimer) {
            clearTimeout(notificationTimer);
        }

        // 1.5 秒后隐藏通知
        notificationTimer = setTimeout(function() {
            NotificationContainer.style.display = 'none';
        }, 1500);

        // 在显示图片之前将容器宽度设置为合适的值
        NotificationContainer.style.width = showImage ? '300px' : 'auto';

        // 如果指定了显示图片,则读取剪贴板中的图片并显示
        if (showImage) {
            NotificationContainer.style.padding = '5px';
            navigator.clipboard.read().then(async function(data) {
                for (const item of data) {
                    for (const type of item.types) {
                        if (type.startsWith('image/')) {
                            const blob = await item.getType(type);
                            const imageURL = URL.createObjectURL(blob);

                            const imageElement = document.createElement('img');
                            imageElement.src = imageURL;
                            imageElement.style.width = '300px'; // 控制图片宽度为其实际大小的40%
                            imageElement.style.borderRadius = '6px'; // 添加圆角样式

                            const imageContainer = document.createElement('div');
                            imageContainer.style.paddingTop = '10px';
                            imageElement.style.maxWidth = '290px';
                            imageContainer.style.borderRadius = '6px'; // 添加圆角样式
                            imageContainer.style.margin = 'auto'; // 居中
                            imageContainer.style.display = 'block'; // 设置为 block,使其单独占据一行
                            // imageContainer.style.overflow = 'hidden'; // 裁剪多余部分
                            imageContainer.appendChild(imageElement);

                            NotificationContainer.appendChild(imageContainer);

                            break;
                        }
                    }
                }
            }).catch(function(error) {
                console.error('Error reading clipboard:', error);
            });
        }
    }


    // 添加鼠标移入事件监听器
    NotificationContainer.addEventListener('mouseenter', function() {
        // 清除计时器
        if (notificationTimer) {
            clearTimeout(notificationTimer);
        }
    });

    // 添加鼠标移出事件监听器
    NotificationContainer.addEventListener('mouseleave', function() {
        // 刷新计时器
        notificationTimer = setTimeout(function() {
            NotificationContainer.style.display = 'none';
        }, 1500);
    });

    async function clickButton(pastedData = true,delayTime, containerSelector, buttonSelector) {
        // 判断粘贴内容是否为空或为 true
        if (pastedData === true || pastedData.trim().length > 0) {
            // 查找指定容器内的按钮
            var container = document.querySelector(containerSelector);
            if (container) {
                var button = container.querySelector(buttonSelector);
                if (button) {
                    setTimeout(function() {
                        button.click();
                    }, delayTime);
                }
            }
        }
    }

    // 监听粘贴事件
    document.addEventListener('paste', function(event) {
        // 判断是否开启了自动点击功能且在匹配的网址上
        if (toggleSwitch.getAttribute('aria-checked') === 'true' && isHomeURL()) {
            // 获取粘贴板中的内容
            var pastedData = (event.clipboardData || window.clipboardData).getData('text');
            var className = '.ant-btn.css-9fw9up.ant-btn-primary';
            clickButton(pastedData, 100,className);
        }
    });

    // 检查文本中是否是天猫链接函数
    function checkForTmallInClipboard(text) {
        const regex = /https:\/\/[^ ]*tmall[^ ]*id=\d{12}/;
        return regex.test(text);
    }

    function checkForChaoshiInClipboard(text) {
        const regex = /https:\/\/[^ ]*chaoshi[^ ]*id=\d{12}/;
        return regex.test(text);
    }

    function checkForFeizhuInClipboard(text) {
        const regex = /https:\/\/[^ ]*fliggy[^ ]*id=\d{12}/;
        return regex.test(text);
    }

    // 提取链接id函数
    function extractIdFromClipboard(text) {
        const idMatch = text.match(/id=(\d{12})/);
        return idMatch ? idMatch[1] : null;
    }

    // 粘贴功能
    async function simulatePaste(targetElement, clearBeforePaste = true) {
        try {
            if(false){
                // 从剪贴板读取文本
                clipboardText = await navigator.clipboard.readText();
            }

            // 检查目标元素是否为可编辑元素
            if (targetElement.isContentEditable || targetElement.tagName === 'INPUT' || targetElement.tagName === 'TEXTAREA') {
                // 如果clearBeforePaste为true,清空目标元素的内容
                if (clearBeforePaste) {
                    if (targetElement.isContentEditable) {
                        targetElement.innerHTML = '';
                    } else {
                        targetElement.value = '';
                    }
                }

                // 插入剪贴板内容到目标元素
                if (document.execCommand('insertText', false, clipboardText)) {
                    // console.log('粘贴成功:' + clipboardText);
                    showNotification("粘贴成功&保存成功");
                } else {
                    targetElement.value += clipboardText;
                }
            } else {
                alert('目标元素不可编辑');
            }
        } catch (err) {
            console.error('读取剪贴板内容失败:', err);
            showNotification("读取剪贴板内容失败");
        }
    }

    function updateClipboardContent() {
        var tmail = "https://detail.tmall.com/item.htm?id=";
        var chaoshi = "https://chaoshi.detail.tmall.com/item.htm?id=";
        var taobao = "https://item.taobao.com/item.htm?id=";
        var feizhu = "https://traveldetail.fliggy.com/item.htm?id=";
        navigator.clipboard.readText().then((clipText) => {
            if(clipText > 29){
                showNotification("剪切板中没有找到链接");
                return;
            }
            const isTmall = checkForTmallInClipboard(clipText);
            const isChaoshi = checkForChaoshiInClipboard(clipText);
            const isFeizhu = checkForFeizhuInClipboard(clipText);
            const itemId = extractIdFromClipboard(clipText);

            if (itemId) {
                var newUrl;
                if(isTmall && !isChaoshi){
                    // 转换为天猫链接
                    newUrl = tmail + itemId;}
                else if(isChaoshi){
                    // 转换为猫超链接
                    newUrl = chaoshi + itemId;
                }
                else if(isFeizhu){
                    // 转换为飞猪链接
                    newUrl = feizhu + itemId;
                }
                else{
                    // 转换为淘宝链接
                    newUrl = taobao + itemId;
                }
                clipboardText = newUrl;
                // GM_setClipboard(newUrl);
                // showNotification("剪贴板内容已更新为:" + newUrl);
                //console.log('剪贴板内容已更新为:' + newUrl);
            } else {
                if(true) GM_setClipboard("12位数字ID不全");// 防止错误粘贴功能
                showNotification("剪贴板中没有找到12位数字ID");
                //console.log('剪贴板中没有找到12位数字ID');
            }
        }).catch((err) => {
            console.error('读取剪贴板失败:', err);
        });
    }

    // 监听鼠标左键点击事件
    document.addEventListener('click', function(event) {
        if (onlyItemIdSwitch.getAttribute('aria-checked') === 'true' && isHomeURL()) {
            if (event.target.closest('.ant-form-item.liveLinkFormItem___RPAQZ.css-9fw9up.ant-form-item-has-success')) {
                if (event.target.classList.contains('ant-input-affix-wrapper') ||
                    event.target.classList.contains('ant-input-affix-wrapper-status-error') ||
                    event.target.classList.contains('css-9fw9up')) {
                    // console.log('目标元素被点击');
                    updateClipboardContent();
                    simulatePaste(document.activeElement);

                    // 点击保存按钮
                    if(true) {
                        var fbutton = '.ant-drawer-footer';
                        var buttonName = '.ant-btn.css-9fw9up.ant-btn-primary';
                        clickButton(undefined, 300, fbutton, buttonName);
                    }
                }
            }
        }
    });

    /*     快捷截图功能区 */
    if(tableCardPngSwitch.getAttribute('aria-checked') === 'true' && isTableCardURL()){
        // Load html2canvas library
        function loadHtml2Canvas(callback) {
            var script = document.createElement('script');
            script.src = 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js';
            script.onload = callback;
            document.head.appendChild(script);
        }

        function createCaptureScreenshotButton() {
            const targetClass = '[class*="ant-space"][class*="css-9fw9up"][class*="ant-space-horizontal"][class*="ant-space-align-center"]';

            const observer = new MutationObserver((mutationsList, observer) => {
                for (let mutation of mutationsList) {
                    if (mutation.type === 'childList') {
                        const targetElement = document.querySelector(targetClass);
                        if (targetElement) {
                            if (document.querySelector('.captureScreenshot')) {
                                observer.disconnect();
                                return;
                            }

                            var captureScreenshot = document.createElement('div');
                            captureScreenshot.classList.add('ant-space-item');

                            var captureScreenshotButton = document.createElement('button');
                            captureScreenshotButton.textContent = '快捷截图';
                            captureScreenshotButton.classList.add('ant-btn', 'css-9fw9up', 'ant-btn-default', 'captureScreenshot');
                            captureScreenshot.appendChild(captureScreenshotButton);

                            // targetElement.insertBefore(captureScreenshot, targetElement.firstChild);

                            captureScreenshotButton.addEventListener('click', captureScreenshotFunction);

                            observer.disconnect();
                            break;
                        }
                    }
                }
            });

            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        function loadImageAsDataURL(url) {
            return new Promise((resolve, reject) => {
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: url,
                    responseType: 'blob',
                    onload: function(response) {
                        const blob = response.response;
                        const reader = new FileReader();
                        reader.onloadend = function() {
                            resolve(reader.result);
                        };
                        reader.onerror = function() {
                            reject(new Error('Failed to load image'));
                        };
                        reader.readAsDataURL(blob);
                    },
                    onerror: function() {
                        reject(new Error('Network error'));
                    }
                });
            });
        }

        async function captureScreenshotFunction() {
            const tableElement = document.querySelector('table');
            var displayScale = 2.5;
            showNotification("截图中···");
            if (tableElement) {
                const rows = tableElement.querySelectorAll('tr');

                if (rows.length >= 3) {
                    rows[2].cells[0].textContent = '';

                    // 隐藏除第二行和第三行外的所有行
                    rows.forEach((row, index) => {
                        if (index !== 1 && index !== 2) {
                            row.style.display = 'none';
                        }
                    });

                    const imgElement = rows[2].cells[2].querySelector('img');
                    if (imgElement) {
                        try {
                            const dataUrl = await loadImageAsDataURL(imgElement.src);
                            imgElement.src = dataUrl;

                            setTimeout(() => {
                                // 使用 html2canvas 捕获截图
                                html2canvas(tableElement, { scale: displayScale }).then(canvas => {
                                    // 恢复所有行的显示状态
                                    rows.forEach(row => {
                                        row.style.display = '';
                                    });

                                    canvas.toBlob(async function(blob) {
                                        try {
                                            await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
                                            console.log("%cTable Screenshot:", "color: #9147ff", "Screenshot copied to clipboard.");
                                            showNotification("截图已成功复制到剪贴板", true);
                                        } catch (error) {
                                            console.log("%cTable Screenshot: Screenshot failed to copy to clipboard!", "color: #ff8080");
                                            showNotification("截图失败!");
                                        }
                                    });
                                });
                            }, 200); // 延迟 200 毫秒等待图片加载完毕
                        } catch (error) {
                            console.log('Image load error:', error);
                        }
                    } else {
                        console.log('Image element not found');
                    }
                } else {
                    console.log("Table does not have enough rows");
                }
            } else {
                console.log("Table element not found");
            }
        }

        loadHtml2Canvas(createCaptureScreenshotButton);}
})();