toolkit - Theo

toolkit

Terá de instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

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

Terá de instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Terá de instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Terá de instalar uma extensão como Tampermonkey para instalar este script.

Terá de instalar uma extensão de gestão de scripts de utilizador para instalar este script.

(Já tenho um gestor de scripts de utilizador, deixe-me instalá-lo!)

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

(Já tenho um gestor de estilos de utilizador, deixe-me instalá-lo!)

// ==UserScript==
// @name         toolkit - Theo
// @namespace    http://tampermonkey.net/
// @version      2026.08.06
// @description  toolkit
// @author       Theo·Chan
// @license      AGPL
// @match        *://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        GM_registerMenuCommand
// ==/UserScript==

(function () {
    'use strict';
    console.log('toolkit - Theo');
    //--------------------------复制为Markdown链接----------------------------------------------------//
    // 注册右键菜单项
    GM_registerMenuCommand('复制为Markdown链接', () => {
        const markdownLink = `[${document.title}](${window.location.href})`;
        console.log(markdownLink);
        // 复制到剪贴板
        copyText(markdownLink);
    });
    function copyText(markdownLink) {
        let _nav = window.navigator;
        // 优先使用 Clipboard API
        if (_nav.isPrototypeOf('clipboard') && _nav.clipboard && window.isSecureContext) {
            _nav.clipboard.writeText(markdownLink)
                .then(() => createToast("已复制为Markdown链接"))
                .catch(() => fallbackCopy(markdownLink));
        } else {
            fallbackCopy(markdownLink);
        }
    }

    function fallbackCopy(text) {
        const textarea = document.createElement("textarea");
        textarea.value = text;
        document.body.appendChild(textarea);
        textarea.select();
        try {
            document.execCommand("copy");
            createToast("已复制为Markdown链接:<br/>" + text);
        } catch (err) {
            createToast("复制失败,请手动复制:<br/>" + text, false, 10000);
        }
        document.body.removeChild(textarea);
    }

    // 创建提示框元素
    const createToast = (content, isSuccess = true, timeOut = 1500) => {
        const toast = document.createElement('div');
        toast.innerHTML = content;
        toast.style = `
            position: fixed;
            word-break: break-all;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            padding: 12px 24px;
            color: ${isSuccess ? '#4CAF50' : '#F44336'};
            border-radius: 4px;
            z-index: 99999;
            opacity: 1;
            background-color: ${isSuccess ? 'rgb(34 57 54 / 80%)' : 'rgb(254 225 164 / 80%)'};
            transition: opacity 0.5s ease-out;
        `;
        document.body.appendChild(toast);

        // 触发淡出
        setTimeout(() => {
            toast.style.opacity = 0;
            toast.addEventListener('transitionend', () => {
                toast.remove();
            }, { once: true });
        }, timeOut); // 显示 1.5 秒后开始淡出

        return toast;
    };

    // pc QQ 安全提醒页面的自动跳转
    function qqAutoGo() {
      if (window.location.hostname !== 'c.pc.qq.com' || window.location.pathname !== '/middlem.html') {
        return;
      }

      const pfUrl = new URLSearchParams(window.location.search).get('pfurl');
      if (!pfUrl) {
        return;
      }

      let targetUrl;
      try {
        targetUrl = decodeURIComponent(pfUrl);
      } catch (error) {
        targetUrl = pfUrl;
      }

      const container = document.querySelector('.url-container');
      if (!container) {
        console.warn('未找到 .url-container 元素,无法显示倒计时跳转提示。');
        // 等待 1 秒后重试
        setTimeout(qqAutoGo, 1000);
        return;
      }

      var countdown = 10;
      const wrapper = document.createElement('div');
      wrapper.style.cssText = 'display:inline-flex;align-items:center;flex-wrap:wrap;gap:10px;margin-top:10px;';

      const countdownValue = document.createElement('span');
      countdownValue.style.cssText = 'font-weight:600;';
      countdownValue.textContent = `${countdown}`;
      countdownValue.title = '剩余秒数';

      const countdownLabel = document.createElement('span');
      countdownLabel.style.cssText = 'display:inline-flex;align-items:center;gap:5px;font-size:14px;color:#e96725;';
      countdownLabel.appendChild(countdownValue);
      countdownLabel.appendChild(document.createTextNode('秒后跳转,按 Esc 取消'));

      const jumpLink = document.createElement('a');
      jumpLink.href = targetUrl;
      jumpLink.textContent = '立即跳转';
      jumpLink.style.cssText = 'color:var(--brand_standard);text-decoration:underline;cursor:pointer;font-size:14px;';
      jumpLink.title = '点击立即跳转到目标页面';

      wrapper.append(countdownLabel);
      container.parentNode.insertBefore(jumpLink, container.nextSibling);
      container.parentNode.insertBefore(wrapper, container.nextSibling);

      let cancelled = false;
      const cleanup = () => {
        window.clearInterval(intervalId);
        document.removeEventListener('keydown', onKeyDown);
      };

      const cancelJump = () => {
        if (cancelled) {
          return;
        }
        cancelled = true;
        cleanup();
        countdownLabel.innerHTML = '已取消跳转';
        createToast('已取消自动跳转', true, 2000);
      };

      const onKeyDown = (event) => {
        if (event.key === 'Escape' || event.key === 'Esc') {
          cancelJump();
        }
      };

      const tick = () => {
        countdown -= 1;
        if (countdown <= 0) {
          cleanup();
          window.location.href = targetUrl;
          return;
        }
        countdownValue.textContent = `${countdown}`;
      };

      const intervalId = window.setInterval(tick, 1000);
      document.addEventListener('keydown', onKeyDown);
    }

    qqAutoGo();
}) ();