Greasy Fork

Greasy Fork is available in English.

机场密码管理器支持

修改机场网站的登录表单,使其能被密码管理器自动识别

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         机场密码管理器支持
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  修改机场网站的登录表单,使其能被密码管理器自动识别
// @author       Seameee
// @match        *://*/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 配置对象
    const config = {
        emailSelector: 'input[placeholder="邮箱"]',
        passwordSelector: 'input[placeholder="密码"]',
        maxAttempts: 50, // 最大尝试次数
        interval: 300    // 检查间隔(毫秒)
    };

    // 全局变量存储观察器和定时器,用于清理
    let domObserver = null;
    let routeObserver = null;
    let pollInterval = null;
    let initExecuted = false;

    // 清理所有资源
    function cleanup() {
        if (domObserver) {
            domObserver.disconnect();
            domObserver = null;
            console.log('🧹 DOM观察器已断开');
        }
        if (routeObserver) {
            routeObserver.disconnect();
            routeObserver = null;
            console.log('🧹 路由观察器已断开');
        }
        if (pollInterval) {
            clearInterval(pollInterval);
            pollInterval = null;
            console.log('🧹 轮询定时器已清除');
        }
    }

    // 检测目标脚本元素
    function hasTargetScript() {
        const targetScript = document.querySelector(
            'script[type="module"][crossorigin][src*="/theme/Xboard/assets/umi.js"]'
        );
        return targetScript !== null;
    }

    // 修改输入框属性以支持密码管理器
    function modifyInputFields() {
        const emailInput = document.querySelector(config.emailSelector);
        const passwordInput = document.querySelector(config.passwordSelector);

        if (emailInput && passwordInput) {
            console.log('找到登录表单,开始修改属性...');

            // 修改邮箱输入框
            if (emailInput.type === 'text') {
                emailInput.type = 'email';
                emailInput.setAttribute('autocomplete', 'username');
                emailInput.setAttribute('name', 'email');
                emailInput.setAttribute('id', 'email');
                console.log('✅ 邮箱输入框已修改');
            }

            // 修改密码输入框
            if (passwordInput.type === 'password') {
                passwordInput.setAttribute('autocomplete', 'current-password');
                passwordInput.setAttribute('name', 'password');
                passwordInput.setAttribute('id', 'password');
                console.log('✅ 密码输入框已修改');
            }

            // 为表单添加 autocomplete 属性
            const form = emailInput.closest('form') || passwordInput.closest('form');
            if (form) {
                form.setAttribute('autocomplete', 'on');
                console.log('✅ 表单已添加 autocomplete 属性');
            }

            return true; // 修改成功
        }
        return false; // 未找到元素
    }

    // 使用 MutationObserver 监控DOM变化
    function setupMutationObserver() {
        // 如果已存在观察器,先断开
        if (domObserver) {
            domObserver.disconnect();
        }

        domObserver = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.addedNodes.length > 0) {
                    // 检查是否有新节点添加
                    modifyInputFields();
                }
            });
        });

        // 开始观察整个文档
        domObserver.observe(document.body, {
            childList: true,
            subtree: true
        });

        console.log('🔍 DOM观察器已启动');
    }

    // 轮询检查元素是否存在
    function pollForElements() {
        let attempts = 0;

        // 清除之前的定时器
        if (pollInterval) {
            clearInterval(pollInterval);
        }

        pollInterval = setInterval(() => {
            attempts++;

            if (modifyInputFields()) {
                clearInterval(pollInterval);
                pollInterval = null;
                console.log('🎉 脚本执行完成');
                return;
            }

            if (attempts >= config.maxAttempts) {
                clearInterval(pollInterval);
                pollInterval = null;
                console.log('⚠️ 达到最大尝试次数,停止检查');
            }
        }, config.interval);
    }

    // 页面加载完成后执行
    function init() {
        // 防止重复执行
        if (initExecuted) {
            return;
        }
        initExecuted = true;

        // 立即检测目标元素
        if (hasTargetScript()) {
            console.log('🎯 检测到目标脚本,开始执行功能');

            // 立即尝试修改
            if (modifyInputFields()) {
                console.log('🎉 立即修改成功');
                // 启动路由监听
                setupRouteChangeListener();
                return;
            }

            // 设置DOM观察器
            setupMutationObserver();

            // 开始轮询检查
            pollForElements();

            // 启动路由监听
            setupRouteChangeListener();
        } else {
            console.log('❌ 未检测到目标脚本,脚本停止运行');
            // 完全停止,不进行任何操作
            return;
        }
    }

    // 等待页面加载完成
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // 监听路由变化(对于SPA应用)
    function setupRouteChangeListener() {
        // 如果已存在观察器,先断开
        if (routeObserver) {
            routeObserver.disconnect();
        }

        let lastUrl = location.href;
        routeObserver = new MutationObserver(() => {
            const url = location.href;
            if (url !== lastUrl) {
                lastUrl = url;
                console.log('🔄 检测到路由变化,重新检查表单');
                setTimeout(modifyInputFields, 1000);
            }
        });

        routeObserver.observe(document, { subtree: true, childList: true });
        console.log('🛣️ 路由变化监听器已启动');
    }

    // 监听页面卸载事件,清理资源
    window.addEventListener('beforeunload', cleanup);
    window.addEventListener('unload', cleanup);

    // 对于SPA应用,监听页面隐藏事件
    document.addEventListener('visibilitychange', function() {
        if (document.visibilityState === 'hidden') {
            cleanup();
        }
    });

})();