Greasy Fork

Greasy Fork is available in English.

自动跳转vpn 公司自用

自动套转 vpn

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         自动跳转vpn 公司自用
// @version      2025-7-31
// @description  自动套转 vpn
// @author       joans
// @match        https://supnet.menusifu.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=menusifu.com
// @grant        none
// @license MIT
// @namespace http://greasyfork.icu/users/1368348
// ==/UserScript==

(function () {
	'use strict'

	// 配置选项
	const config = {
		buttonName: '搜索', // 要监控的按钮名称
		checkInterval: 1000, // 检查间隔(毫秒)
		maxChecks: 30, // 最大检查次数(0=无限)
		debug: true, // 显示调试信息
		highlightButton: true, // 高亮显示找到的按钮
		preventDoubleClick: true, // 防止双击
	}

	// 日志函数
	const log = config.debug
		? (...args) => console.log('[搜索监控]', ...args)
		: () => {}

	log(`开始监控名称为"${config.buttonName}"的按钮...`)

	let checkCount = 0
	let clickHandlerAttached = false

	// 创建监控定时器
	const intervalId = setInterval(() => {
		if (config.maxChecks > 0 && checkCount >= config.maxChecks) {
			log(`已达最大检查次数 (${config.maxChecks}),停止监控`)
			clearInterval(intervalId)
			return
		}

		checkCount++
		log(`第 ${checkCount} 次检查`)

		// 查找所有按钮元素
		const buttons = document.querySelectorAll(
			'button, input[type="button"], input[type="submit"], a'
		)
		let targetButton = null

		// 遍历按钮查找目标
		for (const button of buttons) {
			const buttonText = getButtonText(button)

			if (buttonText.includes(config.buttonName)) {
				log(`发现目标按钮: "${buttonText}"`)
				targetButton = button
				break
			}
		}

		// 如果找到按钮
		if (targetButton && !targetButton.dataset.monitored) {
			// 绑定点击事件
			attachClickHandler(targetButton)

			// 标记按钮已处理
			targetButton.dataset.monitored = 'true'

			// 高亮按钮
			if (config.highlightButton) {
				highlightSearchButton(targetButton)
			}

			// 停止监控
			clearInterval(intervalId)
			log('监控结束')
		}
	}, config.checkInterval)

	// 获取按钮文本
	function getButtonText(button) {
		// 不同按钮类型的文本获取方式
		if (button.tagName === 'INPUT') {
			return button.value || ''
		} else if (button.tagName === 'A') {
			return button.innerText || button.textContent || ''
		} else {
			return button.innerText || button.textContent || button.title || ''
		}
	}

	// 绑定点击事件处理函数
	function attachClickHandler(button) {
		log('绑定点击事件处理函数')

		// 自定义点击处理逻辑
		const customClickHandler = function (event) {
			log(`"${config.buttonName}"按钮被点击`)

			// === 在这里添加你的自定义处理逻辑 ===
			var targetNode = document.querySelector('tbody')
			var delay = null
			// 创建一个观察者对象
			const observer = new MutationObserver((mutations) => {
				mutations.forEach((mutation) => {
					if (delay) {
						clearTimeout(delay)
					}
					log('2')
					// 检测到数据更新后,执行相应的逻辑
					// 这里可以执行数据更新后的逻辑

                    	const runS = () => {
							console.log('runS')

							var ipAddrs = document.querySelectorAll('[title="复制 IP"]')
							log(ipAddrs)
							var toBtu = document.querySelectorAll('.toLinkbtn')
							for (let j = 0; j < toBtu.length; j++) {
								toBtu[j].remove()
							}
							//ipAddr.insertAdjacentHTML("beforeend", "<p>Hello, World!</p>");
							for (let i = 0; i < ipAddrs.length; i++) {
								console.log(ipAddrs[i].parentElement.textContent)

								console.log(
									ipAddrs[i].classList.contains('toLinkbtn')
								)
								ipAddrs[i].parentElement.insertAdjacentHTML(
									'beforeend',
									"<button class='toLinkbtn'  type='button' style='background: none;border: none;'  ><a href='http://" +
										ipAddrs[i].parentElement.textContent +
										":22080/' target='_blank'><svg t='1729050846044' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='4593' width='12' height='12'><path d='M590.665387 86.129778v178.119111c-390.144 0-713.386667 129.649778-544.995556 703.260444-26.396444-358.570667 147.456-471.096889 544.995556-471.096889v174.762667a30.606222 30.606222 0 0 0 52.451555 21.959111l371.768889-291.783111a31.232 31.232 0 0 0 0-44.032l-371.768889-293.205333a30.606222 30.606222 0 1 0-52.451555 22.016z' fill='#666666' p-id='4594'></path></svg><a></button>"
								)
							}
						observer.disconnect()
						}

						delay = setTimeout(runS, 500)
				})
			})

			// 观察者的配置(观察目标节点的子节点的变化)
			const configL = { childList: true, subtree: true }

			// 传入目标节点和观察选项并开始观察
			observer.observe(targetNode, configL)

			// 防止双击
			if (config.preventDoubleClick) {
				button.disabled = true
				setTimeout(() => {
					button.disabled = false
				}, 2000)
			}
		}

		// 绑定事件监听器
		button.addEventListener('click', customClickHandler)
	}

	// 高亮搜索按钮
	function highlightSearchButton(button) {
		button.style.transition = 'all 0.3s ease'
		button.style.boxShadow = '0 0 0 3px rgba(66, 133, 244, 0.5)'
		button.style.border = '2px solid #4285F4'
		button.style.borderRadius = '4px'

		// 添加脉动动画
		let pulseCount = 0
		const pulse = setInterval(() => {
			pulseCount++
			if (pulseCount > 3) {
				clearInterval(pulse)
				return
			}

			button.style.boxShadow = '0 0 0 8px rgba(66, 133, 244, 0.3)'
			setTimeout(() => {
				button.style.boxShadow = '0 0 0 3px rgba(66, 133, 244, 0.5)'
			}, 500)
		}, 1000)

		log('已添加高亮效果')
	}

	// 显示通知
	function showNotification(message) {
		const notification = document.createElement('div')
		notification.textContent = message
		notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 12px 20px;
            background: #4285F4;
            color: white;
            border-radius: 4px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            z-index: 10000;
            font-family: Arial, sans-serif;
            font-size: 14px;
            animation: fadeIn 0.3s, fadeOut 0.3s 2.7s;
        `

		// 添加动画样式
		const style = document.createElement('style')
		style.textContent = `
            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(-20px); }
                to { opacity: 1; transform: translateY(0); }
            }
            @keyframes fadeOut {
                from { opacity: 1; transform: translateY(0); }
                to { opacity: 0; transform: translateY(-20px); }
            }
        `
		document.head.appendChild(style)
		document.body.appendChild(notification)

		// 3秒后移除通知
		setTimeout(() => {
			notification.remove()
			style.remove()
		}, 3000)
	}
})();