机场密码管理器支持

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

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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();
        }
    });

})();