Nc.me表单自动填充生成器

生成随机数据并一键填充表单,支持数据保存和恢复,导出功能

目前為 2025-03-29 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Nc.me表单自动填充生成器 
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  生成随机数据并一键填充表单,支持数据保存和恢复,导出功能
// @author       cursor 0.46.11
// @match        *://*.namecheap.com/*
// @match        *://*.nc.me/*
// @grant        GM_setValue
// @grant        GM_getValue
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 数据生成工具 - 内联数据避免外部依赖
    const DataGenerator = {
        // 美国常用名
        firstNames: ["John", "Jane", "Alex", "Emily", "Chris", "Katie", "Mike", "Laura", "David", "Sarah", 
                     "Robert", "Amanda", "James", "Jennifer", "Michael", "Elizabeth", "William", "Jessica", 
                     "Thomas", "Melissa", "Kevin", "Rachel", "Brian", "Nicole", "Steven", "Michelle"],
        
        // 美国常用姓
        lastNames: ["Smith", "Johnson", "Brown", "Williams", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", 
                   "Martinez", "Wilson", "Anderson", "Taylor", "Thomas", "Moore", "Jackson", "Martin", "Lee",
                   "Thompson", "White", "Harris", "Clark", "Lewis", "Young", "Walker", "Hall"],
        
        // 美国常用街道名
        streetNames: ["Main", "Oak", "Park", "Pine", "Maple", "Cedar", "Elm", "Washington", "Lake", "Hill",
                    "Walnut", "Spring", "North", "South", "East", "West", "Center", "River", "Church"],
        
        // 美国常用街道类型
        streetTypes: ["St", "Ave", "Blvd", "Dr", "Rd", "Ln", "Way", "Pl", "Ct", "Terrace", "Circle", "Drive"],
        
        // 美国常用城市
        cities: ["New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "Philadelphia", "San Antonio", 
                "San Diego", "Dallas", "San Jose", "Austin", "Jacksonville", "Fort Worth", "Columbus", 
                "Charlotte", "San Francisco", "Indianapolis", "Seattle", "Denver", "Boston"],
        
        // 美国州
        states: [
            { full: "Alabama", abbr: "AL" }, { full: "Alaska", abbr: "AK" },
            { full: "Arizona", abbr: "AZ" }, { full: "Arkansas", abbr: "AR" },
            { full: "California", abbr: "CA" }, { full: "Colorado", abbr: "CO" },
            { full: "Connecticut", abbr: "CT" }, { full: "Delaware", abbr: "DE" },
            { full: "Florida", abbr: "FL" }, { full: "Georgia", abbr: "GA" },
            { full: "Hawaii", abbr: "HI" }, { full: "Idaho", abbr: "ID" },
            { full: "Illinois", abbr: "IL" }, { full: "Indiana", abbr: "IN" },
            { full: "Iowa", abbr: "IA" }, { full: "Kansas", abbr: "KS" },
            { full: "Kentucky", abbr: "KY" }, { full: "Louisiana", abbr: "LA" },
            { full: "Maine", abbr: "ME" }, { full: "Maryland", abbr: "MD" },
            { full: "Massachusetts", abbr: "MA" }, { full: "Michigan", abbr: "MI" },
            { full: "Minnesota", abbr: "MN" }, { full: "Mississippi", abbr: "MS" },
            { full: "Missouri", abbr: "MO" }, { full: "Montana", abbr: "MT" },
            { full: "Nebraska", abbr: "NE" }, { full: "Nevada", abbr: "NV" },
            { full: "New Hampshire", abbr: "NH" }, { full: "New Jersey", abbr: "NJ" },
            { full: "New Mexico", abbr: "NM" }, { full: "New York", abbr: "NY" },
            { full: "North Carolina", abbr: "NC" }, { full: "North Dakota", abbr: "ND" },
            { full: "Ohio", abbr: "OH" }, { full: "Oklahoma", abbr: "OK" },
            { full: "Oregon", abbr: "OR" }, { full: "Pennsylvania", abbr: "PA" },
            { full: "Rhode Island", abbr: "RI" }, { full: "South Carolina", abbr: "SC" },
            { full: "South Dakota", abbr: "SD" }, { full: "Tennessee", abbr: "TN" },
            { full: "Texas", abbr: "TX" }, { full: "Utah", abbr: "UT" },
            { full: "Vermont", abbr: "VT" }, { full: "Virginia", abbr: "VA" },
            { full: "Washington", abbr: "WA" }, { full: "West Virginia", abbr: "WV" },
            { full: "Wisconsin", abbr: "WI" }, { full: "Wyoming", abbr: "WY" }
        ],
        
        // 随机数生成
        randomInt: function(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        },
        
        // 随机选择数组元素
        randomElement: function(array) {
            return array[this.randomInt(0, array.length - 1)];
        },
        
        // 生成随机字符串
        randomString: function(length, chars) {
            chars = chars || 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
            let result = '';
            for (let i = 0; i < length; i++) {
                result += chars.charAt(Math.floor(Math.random() * chars.length));
            }
            return result;
        },
        
        // 生成随机用户名 - 只包含字母和数字
        getUserName: function(firstName, lastName) {
            if (!firstName || !lastName) {
                firstName = this.randomElement(this.firstNames);
                lastName = this.randomElement(this.lastNames);
            }
            
            // 生成几种可能的用户名格式 - 仅使用字母和数字
            const formats = [
                firstName.toLowerCase() + lastName.toLowerCase(),
                firstName.toLowerCase() + this.randomInt(1, 999),
                firstName.toLowerCase() + lastName.toLowerCase() + this.randomInt(1, 99),
                firstName.toLowerCase().substring(0, 1) + lastName.toLowerCase() + this.randomInt(100, 999),
                firstName.toLowerCase() + this.randomInt(1000, 9999)
            ];
            
            // 获取一个随机格式的用户名
            let username = this.randomElement(formats);
            
            // 确保只包含字母和数字
            username = username.replace(/[^a-z0-9]/g, '');
            
            return username;
        },
        
        // 生成随机密码
        getPassword: function(length, includeSpecial) {
            length = length || 10;
            let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            if (includeSpecial) {
                chars += "!@#$%^&*()_+~`|}{[]\\:;?><,./-=";
            }
            return this.randomString(length, chars);
        },
        
        // 生成随机街道地址
        getStreetAddress: function() {
                const number = this.randomInt(100, 9999);
                const street = this.randomElement(this.streetNames);
                const type = this.randomElement(this.streetTypes);
                return number + " " + street + " " + type;
        },
        
        // 生成随机公寓/单元号
        getSecondaryAddress: function() {
                const formats = [
                    "Apt " + this.randomInt(1, 999),
                    "Suite " + this.randomInt(1, 999),
                    "Unit " + this.randomInt(1, 999),
                    "#" + this.randomInt(1, 999)
                ];
                return this.randomElement(formats);
        },
        
        // 生成随机邮编
        getZipCode: function() {
                return "" + this.randomInt(10000, 99999);
        },
        
        // 生成随机电话号码 - 使用(xxx) xxx-xxxx格式
        getPhoneNumber: function() {
            const areaCode = this.randomInt(200, 999);
            const prefix = this.randomInt(200, 999);
            const lineNumber = this.randomInt(1000, 9999);
            
            return `(${areaCode}) ${prefix}-${lineNumber}`;
        },
        
        // 生成完整个人信息数据集
        generatePersonData: function() {
            const firstName = this.randomElement(this.firstNames);
            const lastName = this.randomElement(this.lastNames);
            const state = this.randomElement(this.states);
            
            return {
                username: this.getUserName(firstName, lastName),
                password: this.getPassword(12, true),
                email: "请自行填写用于验证的邮箱", // 固定值
                firstName: firstName,
                lastName: lastName,
                addressLine1: this.getStreetAddress(),
                addressLine2: this.getSecondaryAddress(),
                city: this.randomElement(this.cities),
                state: state.full,
                stateAbbr: state.abbr,
                postalCode: this.getZipCode(),
                phone: this.getPhoneNumber(),
                timestamp: new Date().toLocaleString(),
                filled: false // 添加填充状态标记
            };
        }
    };

    // 数据存储工具 - 使用GM API
    const DataStorage = {
        storageKey: 'formFiller_NamecheapData',
        
        // 检查用户名是否已存在 
        isUsernameDuplicate: function(username) {
            const allData = this.getAllData();
            return allData.some(item => item.username === username);
        },
        
        // 保存数据
        saveData: function(data) {
            try {
                // 首先检查用户名是否已经存在
                if (this.isUsernameDuplicate(data.username)) {
                    return { success: false, message: '该用户名已存在于保存的数据中' };
                }
                
                // 获取现有数据
                let savedData = this.getAllData();
                
                // 生成唯一ID
                data.id = Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
                savedData.push(data);
                
                // 使用GM_setValue保存数据
                GM_setValue(this.storageKey, savedData);
                
                console.log("数据已保存", data);
                return { success: true, id: data.id };
            } catch(e) {
                console.error("保存数据失败:", e);
                return { success: false, message: "保存数据失败: " + e.message };
            }
        },
        
        // 获取所有保存的数据
        getAllData: function() {
            try {
                // 使用GM_getValue获取数据
                const data = GM_getValue(this.storageKey, []);
                console.log("读取的数据:", data);
                return data;
            } catch(e) {
                console.error("读取数据失败:", e);
                return [];
            }
        },
        
        // 获取指定ID的数据
        getData: function(id) {
            const allData = this.getAllData();
            return allData.find(item => item.id === id);
        },
        
        // 删除数据
        deleteData: function(id) {
            let allData = this.getAllData();
            allData = allData.filter(item => item.id !== id);
            GM_setValue(this.storageKey, allData);
        },
        
        // 清空所有数据
        clearAllData: function() {
            GM_setValue(this.storageKey, []);
        },
        
        // 导出所有数据为文本
        exportDataAsText: function() {
            const allData = this.getAllData();
            if (allData.length === 0) {
                return "没有保存的数据";
            }
            
            let text = "表单填充数据导出 - " + new Date().toLocaleString() + "\n\n";
            
            allData.forEach((data, index) => {
                text += `--- 记录 ${index + 1} ---\n`;
                text += `姓名: ${data.firstName} ${data.lastName}\n`;
                text += `用户名: ${data.username}\n`;
                text += `密码: ${data.password}\n`;
                text += `邮箱: ${data.email || '未填写'}\n`;
                text += `地址: ${data.addressLine1}\n`;
                text += `地址2: ${data.addressLine2 || '无'}\n`;
                text += `城市: ${data.city}\n`;
                text += `州/省: ${data.state}\n`;
                text += `邮编: ${data.postalCode}\n`;
                text += `电话: ${data.phone}\n`;
                text += `保存时间: ${data.timestamp || '未知'}\n\n`;
            });
            
            return text;
        }
    };

    // 存储生成的数据、表单填充状态和邮箱填写状态
    let generatedData = {};
    let hasFilledForm = false;
    let emailFilled = false; 
    let userFilledEmail = ""; 

    // 创建UI
    const UI = {
        panel: null,
        dataContainer: null,
        savedDataContainer: null,
        saveButton: null,
        showSavedData: false,
        buttonContainer: null,
        secondRowContainer: null,
        notificationArea: null, 
        
        // 初始化UI
        init: function() {
            // 检测当前页面类型
            const isSignInPage = window.location.href.includes('/login') || 
                                window.location.href.includes('/signin');
            
            // 创建控制面板 - 统一上边界高度
            this.panel = document.createElement('div');
            this.panel.style.cssText = `
                position: fixed;
                top: 200px;
                left: 20px;
                width: 350px;
                background: #f8f9fa;
                border: 1px solid #ddd;
                border-radius: 5px;
                padding: 10px;
                z-index: 10000;
                box-shadow: 0 0 10px rgba(0,0,0,0.1);
                max-height: ${isSignInPage ? '90vh' : '75vh'};
                overflow-y: auto;
            `;

            // 创建标题 - 缩小边距
            const title = document.createElement('h3');
            title.textContent = 'Nc.me表单填写助手';
            title.style.cssText = `
                margin: 0 0 8px 0; 
                color: #333; 
                font-size: 16px; 
                text-align: center; 
                padding: 6px 0; 
                background-color: #f1f8e9; 
                border-radius: 4px; 
                border-bottom: 2px solid #4CAF50;
                font-weight: bold;
                box-shadow: 0 1px 3px rgba(0,0,0,0.1);
            `;
            this.panel.appendChild(title);
            
            // 创建通知区域 - 在标题下方
            this.notificationArea = document.createElement('div');
            this.notificationArea.style.cssText = `
                margin: -10px 0 10px 0;
                padding: 0;
                min-height: 30px;
                text-align: center;
            `;
            this.panel.appendChild(this.notificationArea);
            
            // 如果是登录(不可用)页面,只显示保存的数据
            if (isSignInPage) {
                this.savedDataContainer = document.createElement('div');
                this.savedDataContainer.id = 'saved-data';
                this.panel.appendChild(this.savedDataContainer);
                
                // 显示保存的数据
                this.displaySavedData();
            } else {
                // 注册(不可用)页面的完整UI
                this.dataContainer = document.createElement('div');
                this.dataContainer.id = 'faker-data';
                this.panel.appendChild(this.dataContainer);

                // 创建保存数据容器
                this.savedDataContainer = document.createElement('div');
                this.savedDataContainer.id = 'saved-data';
                this.savedDataContainer.style.display = 'none';
                this.panel.appendChild(this.savedDataContainer);

                // 创建按钮容器
                this.buttonContainer = document.createElement('div');
                this.buttonContainer.style.cssText = 'display: flex; margin-top: 10px; gap: 6px; flex-wrap: wrap;';
                this.panel.appendChild(this.buttonContainer);

                // 创建生成按钮
                const generateButton = document.createElement('button');
                generateButton.textContent = '重新生成';
                generateButton.style.cssText = `
                    background: #4CAF50;
                    color: white;
                    border: none;
                    padding: 6px 12px;
                    border-radius: 4px;
                    cursor: pointer;
                    flex: 1;
                    min-width: 100px;
                    font-size: 13px;
                `;
                generateButton.onclick = () => {
                    generatedData = DataGenerator.generatePersonData();
                    hasFilledForm = false;
                    emailFilled = false;
                    userFilledEmail = "";
                    
                    // 重置邮箱表单字段
                    const emailField = findFormField('email');
                    if (emailField) {
                        emailField.value = '';
                        emailField.dispatchEvent(new Event('input', { bubbles: true }));
                        emailField.dispatchEvent(new Event('change', { bubbles: true }));
                    }
                    
                    this.updateSaveButtonState();
                    this.displayCurrentData();
                };
                this.buttonContainer.appendChild(generateButton);

                // 创建填充按钮
                const fillButton = document.createElement('button');
                fillButton.textContent = '一键填充';
                fillButton.style.cssText = `
                    background: #2196F3;
                    color: white;
                    border: none;
                    padding: 6px 12px;
                    border-radius: 4px;
                    cursor: pointer;
                    flex: 1;
                    min-width: 100px;
                    font-size: 13px;
                `;
                fillButton.onclick = () => {
                    fillForm();
                    hasFilledForm = true;
                    this.updateSaveButtonState();
                };
                this.buttonContainer.appendChild(fillButton);

                // 创建保存按钮
                this.saveButton = document.createElement('button');
                this.saveButton.textContent = '保存数据';
                this.saveButton.style.cssText = `
                    background: #FF9800;
                    color: white;
                    border: none;
                    padding: 6px 12px;
                    border-radius: 4px;
                    cursor: pointer;
                    flex: 1;
                    min-width: 100px;
                    font-size: 13px;
                    opacity: 0.5;
                `;
                this.saveButton.disabled = true;
                this.saveButton.onclick = () => {
                    if (hasFilledForm && emailFilled) {
                        // 从表单中读取当前值
                        const formData = readFormData();
                        
                        // 显示邮箱确认对话框
                        if (confirm(`请确认填写的邮箱地址是否正确:\n${formData.email}\n\n点击"确定"继续保存,点击"取消"返回修改`)) {
                            const result = DataStorage.saveData(formData);
                            if (result.success) {
                                this.showStatusMessage('数据已保存', 'success');
                                hasFilledForm = false;
                                this.updateSaveButtonState();
                            } else {
                                this.showStatusMessage(result.message, 'warning');
                            }
                        }
                    }
                };
                this.buttonContainer.appendChild(this.saveButton);

                // 第二行按钮
                this.secondRowContainer = document.createElement('div');
                this.secondRowContainer.style.cssText = 'display: flex; margin-top: 10px; gap: 10px;';
                this.panel.appendChild(this.secondRowContainer);

                // 创建数据切换按钮
                const toggleButton = document.createElement('button');
                toggleButton.textContent = '查看保存的数据';
                toggleButton.id = 'toggle-data-view-btn';
                toggleButton.style.cssText = `
                    background: #757575;
                    color: white;
                    border: none;
                    padding: 8px 15px;
                    border-radius: 4px;
                    cursor: pointer;
                    flex: 1;
                `;
                toggleButton.onclick = () => this.toggleDataView();
                this.secondRowContainer.appendChild(toggleButton);

                // 创建导出按钮
                const exportButton = document.createElement('button');
                exportButton.textContent = '导出数据';
                exportButton.style.cssText = `
                    background: #9C27B0;
                    color: white;
                    border: none;
                    padding: 8px 15px;
                    border-radius: 4px;
                    cursor: pointer;
                    flex: 1;
                `;
                exportButton.onclick = () => this.exportData();
                this.secondRowContainer.appendChild(exportButton);
                
                // 显示当前数据
                this.displayCurrentData();
                
                // 添加对表单中邮箱字段的监听
                this.setupEmailListener();
            }

            // 添加面板到文档
            document.body.appendChild(this.panel);
        },
        
        // 邮箱字段的监听器
        setupEmailListener: function() {
            // 使用MutationObserver监听DOM变化
            const observer = new MutationObserver(() => {
                // 尝试查找邮箱字段
                const emailField = findFormField('email');
                if (emailField) {
                    // 获取当前值(如果有的话)
                    if (emailField.value && emailField.value.trim() !== '') {
                        userFilledEmail = emailField.value;
                        emailFilled = true;
                        this.updateSaveButtonState();
                    }
                    
                    // 为邮箱字段添加事件监听器
                    emailField.addEventListener('input', (e) => {
                        userFilledEmail = e.target.value;
                        emailFilled = userFilledEmail.trim() !== '';
                        this.updateSaveButtonState();
                    });
                    
                    // 监听到邮箱字段后可以停止观察
                    observer.disconnect();
                }
            });
            
            // 开始观察文档变化
            observer.observe(document.body, { 
                childList: true, 
                subtree: true 
            });
            
            // 立即尝试查找一次
            const emailField = findFormField('email');
            if (emailField) {
                // 获取当前值(如果有的话)
                if (emailField.value && emailField.value.trim() !== '') {
                    userFilledEmail = emailField.value;
                    emailFilled = true;
                    this.updateSaveButtonState();
                }
                
                emailField.addEventListener('input', (e) => {
                    userFilledEmail = e.target.value;
                    emailFilled = userFilledEmail.trim() !== '';
                    this.updateSaveButtonState();
                });
            }
        },
        
        // 更新保存按钮状态
        updateSaveButtonState: function() {
            if (hasFilledForm && emailFilled) {
                this.saveButton.disabled = false;
                this.saveButton.style.opacity = '1';
                this.saveButton.style.cursor = 'pointer';
            } else {
                this.saveButton.disabled = true;
                this.saveButton.style.opacity = '0.5';
                this.saveButton.style.cursor = 'not-allowed';
            }
        },
        
        // 导出数据为文本文件
        exportData: function() {
            const text = DataStorage.exportDataAsText();
            const blob = new Blob([text], {type: 'text/plain;charset=utf-8'});
            const url = URL.createObjectURL(blob);
            
            const a = document.createElement('a');
            a.href = url;
            a.download = `Nc.me账户数据_${new Date().toISOString().slice(0,10)}.txt`;
            document.body.appendChild(a);
            a.click();
            
            // 清理
            setTimeout(() => {
                document.body.removeChild(a);
                URL.revokeObjectURL(url);
            }, 100);
            
            this.showStatusMessage('数据已导出', 'success');
        },
        
        // 显示当前生成的数据 
        displayCurrentData: function() {
            // 创建表格显示数据
            let html = '<table style="width:100%; border-collapse: collapse; font-size: 14px;">';
            
            for (const [key, value] of Object.entries(generatedData)) {
                // 不显示一些重复或不必要的字段
                if (key === 'id' || key === 'timestamp' || key === 'stateAbbr' || key === 'filled') continue;
                
                // 特殊处理email字段,显示用户输入的值或红色提示信息
                let displayValue = value;
                if (key === 'email') {
                    if (emailFilled) {
                        displayValue = userFilledEmail;
                    } else {
                        // 使用红色字体显示提示信息
                        displayValue = '<span style="color: #FF0000; font-weight: bold;">请填写邮箱后再保存</span>';
                    }
                }
                
                html += `
                    <tr style="border-bottom: 1px solid #eee;">
                        <td style="padding: 4px 0; color: #666; font-weight: bold;">${formatKey(key)}:</td>
                        <td style="padding: 4px 0;">${displayValue}</td>
                    </tr>
                `;
            }
            
            html += '</table>';
            this.dataContainer.innerHTML = html;
        },
        
        // 显示保存的数据列表 - 调整登录(不可用)页面按钮布局
        displaySavedData: function() {
            const savedData = DataStorage.getAllData();
            const isSignInPage = window.location.href.includes('/login') || 
                                window.location.href.includes('/signin');
            
            if (savedData.length === 0) {
                this.savedDataContainer.innerHTML = '<p style="text-align:center; color:#666;">没有保存的数据</p>';
                return;
            }
            
            let html = '';
            
            // 调整登录(不可用)页面按钮布局
            if (!isSignInPage) {
                // 注册(不可用)页面的清空按钮 
                html += `
                    <div style="margin-bottom: 10px;">
                        <button id="clear-all-data" style="background:#f44336; color:white; border:none; padding:5px 10px; border-radius:4px; cursor:pointer;">
                            清空所有数据
                        </button>
                    </div>
                `;
            } else {
                // 登录(不可用)页面 - 左右两侧分别放置清空和导出按钮
                html += `
                    <div style="display:flex; justify-content:space-between; margin-bottom: 8px;">
                        <button id="clear-all-data" style="background:#f44336; color:white; border:none; padding:3px 6px; border-radius:3px; cursor:pointer; font-size: 11px;">
                            清空所有数据
                        </button>
                        <button id="export-data" style="background:#9C27B0; color:white; border:none; padding:3px 6px; border-radius:3px; cursor:pointer; font-size: 11px;">
                            导出数据
                        </button>
                    </div>
                `;
            }
            
            html += '<div style="max-height: 400px; overflow-y: auto;">';
            
            savedData.forEach(data => {
                // 显示邮箱,如果没有则显示提示文本
                const emailDisplay = data.email && data.email !== "用于验证的邮箱" && data.email !== "请自行填写用于验证的邮箱" 
                    ? data.email 
                    : '<span style="color:#999;">未填写邮箱</span>';
                
                if (isSignInPage) {
                    // 登录(不可用)页面 - 更紧凑的卡片
                    html += `
                        <div style="margin-bottom: 6px; padding: 6px; border: 1px solid #ddd; border-radius: 4px;">
                            <div style="display: flex; justify-content: space-between; margin-bottom: 3px;">
                                <span style="font-weight: bold; overflow: hidden; text-overflow: ellipsis; max-width: 200px; font-size: 13px;">${emailDisplay}</span>
                                <span style="color: #666; font-size: 11px;">${data.timestamp || '未知时间'}</span>
                            </div>
                            
                            <div style="margin-bottom: 3px; display: flex; justify-content: space-between; align-items: center; font-size: 13px;">
                                <span>用户名: ${data.username}</span>
                                <button class="copy-btn" data-text="${data.username}" style="background:#4CAF50; color:white; border:none; padding:1px 6px; border-radius:3px; cursor:pointer; font-size: 11px;">
                                    复制
                                </button>
                            </div>
                            
                            <div style="display: flex; justify-content: space-between; align-items: center; font-size: 13px;">
                                <span>密码: ${data.password}</span>
                                <button class="copy-btn" data-text="${data.password}" style="background:#4CAF50; color:white; border:none; padding:1px 6px; border-radius:3px; cursor:pointer; font-size: 11px;">
                                    复制
                                </button>
                            </div>
                        </div>
                    `;
                } else {
                    // 注册(不可用)页面 - 更紧凑的卡片
                    html += `
                        <div style="margin-bottom: 8px; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px;">
                            <div style="display: flex; justify-content: space-between; margin-bottom: 3px;">
                                <span style="font-weight: bold; overflow: hidden; text-overflow: ellipsis; max-width: 200px;">${emailDisplay}</span>
                                <span style="color: #666; font-size: 11px;">${data.timestamp || '未知时间'}</span>
                            </div>
                            
                            <div style="margin-bottom: 3px; display: flex; justify-content: space-between; align-items: center;">
                                <span>用户名: ${data.username}</span>
                                <button class="copy-btn" data-text="${data.username}" style="background:#4CAF50; color:white; border:none; padding:1px 5px; border-radius:3px; cursor:pointer; font-size: 11px;">
                                    复制
                                </button>
                            </div>
                            
                            <div style="margin-bottom: 6px; display: flex; justify-content: space-between; align-items: center;">
                                <span>密码: ${data.password}</span>
                                <button class="copy-btn" data-text="${data.password}" style="background:#4CAF50; color:white; border:none; padding:1px 5px; border-radius:3px; cursor:pointer; font-size: 11px;">
                                    复制
                                </button>
                            </div>
                            
                            <div style="display: flex; gap: 4px;">
                                <button data-id="${data.id}" class="load-data-btn" style="background:#2196F3; color:white; border:none; padding:2px 6px; border-radius:3px; cursor:pointer; flex:1; font-size: 11px;">
                                    加载
                                </button>
                                <button data-id="${data.id}" class="delete-data-btn" style="background:#f44336; color:white; border:none; padding:2px 6px; border-radius:3px; cursor:pointer; flex:1; font-size: 11px;">
                                    删除
                                </button>
                            </div>
                        </div>
                    `;
                }
            });
            
            html += '</div>';
            this.savedDataContainer.innerHTML = html;
            
            // 添加事件监听
            setTimeout(() => {
                // 复制按钮事件监听
                this.savedDataContainer.querySelectorAll('.copy-btn').forEach(btn => {
                    btn.addEventListener('click', (e) => {
                        const textToCopy = e.target.getAttribute('data-text');
                        navigator.clipboard.writeText(textToCopy).then(() => {
                            this.showStatusMessage('已复制到剪贴板', 'success');
                        }).catch(err => {
                            console.error('复制失败:', err);
                            this.showStatusMessage('复制失败', 'error');
                        });
                    });
                });
                
                // 非登录(不可用)页面的按钮事件
                if (!isSignInPage) {
                    this.savedDataContainer.querySelectorAll('.load-data-btn').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.target.getAttribute('data-id');
                            this.loadSavedData(id);
                        });
                    });
                    
                    this.savedDataContainer.querySelectorAll('.delete-data-btn').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.target.getAttribute('data-id');
                            this.deleteSavedData(id);
                        });
                    });
                }
                
                // 清空按钮 - 两种页面都有
                const clearAllBtn = document.getElementById('clear-all-data');
                if (clearAllBtn) {
                    clearAllBtn.addEventListener('click', () => this.clearAllSavedData());
                }
                
                // 登录(不可用)页面专用导出按钮
                if (isSignInPage) {
                    const exportBtn = document.getElementById('export-data');
                    if (exportBtn) {
                        exportBtn.addEventListener('click', () => this.exportData());
                    }
                }
            }, 0);
        },
        
        // 切换数据视图(当前/保存的)
        toggleDataView: function() {
            this.showSavedData = !this.showSavedData;
            
            if (this.showSavedData) {
                this.dataContainer.style.display = 'none';
                this.savedDataContainer.style.display = 'block';
                this.displaySavedData();
                
                // 隐藏主操作按钮
                this.buttonContainer.style.display = 'none';
                
                // 更新切换按钮文字
                const toggleBtn = document.getElementById('toggle-data-view-btn');
                if (toggleBtn) toggleBtn.textContent = '返回当前数据';
            } else {
                this.dataContainer.style.display = 'block';
                this.savedDataContainer.style.display = 'none';
                this.displayCurrentData();
                
                // 显示主操作按钮
                this.buttonContainer.style.display = 'flex';
                
                // 更新切换按钮文字
                const toggleBtn = document.getElementById('toggle-data-view-btn');
                if (toggleBtn) toggleBtn.textContent = '查看保存的数据';
            }
        },
        
        // 加载保存的数据
        loadSavedData: function(id) {
            const data = DataStorage.getData(id);
            if (data) {
                generatedData = data;
                hasFilledForm = false;
                this.updateSaveButtonState();
                this.displayCurrentData();
                this.toggleDataView();
                this.showStatusMessage('数据已加载', 'info');
            }
        },
        
        // 删除保存的数据
        deleteSavedData: function(id) {
            if (confirm('确定要删除这条数据吗?')) {
                DataStorage.deleteData(id);
                this.displaySavedData();
                this.showStatusMessage('数据已删除', 'success');
            }
        },
        
        // 清空所有保存的数据
        clearAllSavedData: function() {
            if (confirm('确定要删除所有保存的数据吗?')) {
                DataStorage.clearAllData();
                this.displaySavedData();
                this.showStatusMessage('所有数据已清空', 'success');
            }
        },
        
        // 显示状态消息 - 改为在面板内显示
        showStatusMessage: function(message, type = 'info') {
            // 清除旧消息
            const oldMessages = this.notificationArea.querySelectorAll('.status-message');
            oldMessages.forEach(msg => msg.remove());
            
            // 创建新消息
            const statusDiv = document.createElement('div');
            statusDiv.textContent = message;
            statusDiv.className = 'status-message';
            
            // 根据消息类型设置不同样式
            let bgColor, textColor = 'white';
            switch(type) {
                case 'success':
                    bgColor = '#4CAF50';
                    break;
                case 'warning':
                    bgColor = '#FF9800';
                    break;
                case 'error':
                    bgColor = '#F44336';
                    break;
                default:
                    bgColor = '#2196F3'; // info
            }
            
            statusDiv.style.cssText = `
                padding: 8px 12px;
                border-radius: 4px;
                color: ${textColor};
                margin: 5px 0;
                animation: fadeIn 0.3s ease-in-out;
                background-color: ${bgColor};
            `;
            
            // 添加到通知区域
            this.notificationArea.appendChild(statusDiv);
            
            // 自动隐藏
            setTimeout(() => {
                statusDiv.style.animation = 'fadeOut 0.5s ease-in-out forwards';
                setTimeout(() => statusDiv.remove(), 500);
            }, 3000);
        }
    };

    // 格式化键名为更友好的显示
    function formatKey(key) {
        return key
            .replace(/([A-Z])/g, ' $1') // 在大写字母前添加空格
            .replace(/^./, str => str.toUpperCase()) // 首字母大写
            .replace(/([a-z])(\d)/, '$1 $2') // 在字母和数字之间添加空格
            .replace('Line', ' Line '); // 处理地址行
    }

    // 填充表单
    function fillForm() {
        // 查找表单字段
        const usernameField = findFormField('username', 'user', 'login');
        const passwordField = findFormField('password', 'pass');
        const confirmPasswordField = findFormField('password_confirmation', 'confirm', 'repeat', 'verif');
        const emailField = findFormField('email');
        const firstNameField = findFormField('first_name', 'firstname', 'fname', 'first name', 'name');
        const lastNameField = findFormField('last_name', 'lastname', 'lname', 'last name', 'surname');
        
        const addressLine1Field = findFormField('address_1', 'address1', 'address-line-1', 'address_line_1', 'address', 'street', 'line1');
        const addressLine2Field = findFormField('address_2', 'address2', 'address-line-2', 'address_line_2', 'apt', 'suite', 'line2');
        
        const cityField = findFormField('city', 'town');
        const stateField = findFormField('state', 'province', 'region');
        const postalCodeField = findFormField('zipcode', 'postal', 'zip', 'postcode');
        const phoneField = findFormField('phone_intl', 'phone', 'telephone', 'mobile', 'cell');

        // 填充字段
        fillField(usernameField, generatedData.username);
        fillField(passwordField, generatedData.password);
        fillField(confirmPasswordField, generatedData.password);
        
        // Email不自动填充,但检查是否已有用户输入的值
        if (emailField) {
            // 如果邮箱字段已有内容,保存用户输入的邮箱值
            if (emailField.value && emailField.value.trim() !== '') {
                userFilledEmail = emailField.value;
                emailFilled = true;
            } else {
                // 如果已经有用户填写的邮箱值,则可以选择保留而不清空
                // 这是可选的,取决于您希望的行为
            }
        }
        
        fillField(firstNameField, generatedData.firstName);
        fillField(lastNameField, generatedData.lastName);
        fillField(addressLine1Field, generatedData.addressLine1);
        fillField(addressLine2Field, generatedData.addressLine2);
        fillField(cityField, generatedData.city);
        fillField(stateField, generatedData.state);
        fillField(postalCodeField, generatedData.postalCode);
        fillField(phoneField, generatedData.phone);

        // 处理额外的电话国家代码字段
        const phoneCountryField = document.querySelector('input[name="phone_country"]');
        if (phoneCountryField) {
            phoneCountryField.value = '1'; // 默认美国国家代码
            phoneCountryField.dispatchEvent(new Event('input', { bubbles: true }));
            phoneCountryField.dispatchEvent(new Event('change', { bubbles: true }));
        }

        // 处理隐藏的电话字段
        const hiddenPhoneField = document.querySelector('input[name="phone"]');
        if (hiddenPhoneField) {
            hiddenPhoneField.value = generatedData.phone;
            hiddenPhoneField.dispatchEvent(new Event('input', { bubbles: true }));
            hiddenPhoneField.dispatchEvent(new Event('change', { bubbles: true }));
        }

        // 显示填充结果
        UI.showStatusMessage('表单已填充', 'success');
        
        // 标记数据已填充状态
        generatedData.filled = true;
        
        // 更新保存按钮状态
        UI.updateSaveButtonState();
        
        // 更新显示的数据为表单中的当前值
        generatedData = readFormData();
        UI.displayCurrentData();
    }

    // 通过多种可能的名称查找表单字段
    function findFormField(...possibleNames) {
        for (const name of possibleNames) {
            // 尝试通过id查找
            let element = document.getElementById(name);
            if (element && isInputElement(element)) return element;

            // 尝试通过name查找
            element = document.querySelector(`[name="${name}"], [name="${name.toLowerCase()}"]`);
            if (element && isInputElement(element)) return element;

            // 尝试通过placeholder查找
            element = document.querySelector(`[placeholder*="${name}"], [placeholder*="${name.toLowerCase()}"]`);
            if (element && isInputElement(element)) return element;

            // 查找特定的确认密码和地址字段
            if (name === 'confirm' || name === 'password_confirmation') {
                element = document.querySelector('input[name="password_confirmation"]');
                if (element) return element;
            }
            
            if (name === 'address_1' || name === 'address1') {
                element = document.querySelector('input[name="address_1"]');
                if (element) return element;
            }
            
            if (name === 'address_2' || name === 'address2') {
                element = document.querySelector('input[name="address_2"]');
                if (element) return element;
            }

            // 尝试通过标签相关文本查找
            const labels = Array.from(document.querySelectorAll('label'));
            for (const label of labels) {
                if (label.textContent.toLowerCase().includes(name.toLowerCase())) {
                    // 检查for属性
                    if (label.htmlFor) {
                        element = document.getElementById(label.htmlFor);
                        if (element && isInputElement(element)) return element;
                    }
                    
                    // 检查嵌套的input
                    element = label.querySelector('input, textarea, select');
                    if (element && isInputElement(element)) return element;
                }
            }
        }

        // 使用更通用的选择器
        for (const name of possibleNames) {
            const elements = document.querySelectorAll('input, textarea, select');
            for (const element of elements) {
                if (!isInputElement(element)) continue;
                
                // 检查是否在附近有相关文本
                const parent = element.parentElement;
                if (parent && parent.textContent.toLowerCase().includes(name.toLowerCase())) {
                    return element;
                }

                // 检查placeholder属性是否含有相关文本
                const placeholder = element.getAttribute('placeholder');
                if (placeholder && placeholder.toLowerCase().includes(name.toLowerCase())) {
                    return element;
                }
            }
        }

        return null;
    }

    // 判断是否是输入元素
    function isInputElement(element) {
        if (!element) return false;
        return element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT';
    }

    // 填充字段
    function fillField(field, value) {
        if (!field || !value) return;

        // 设置值
        field.value = value;
        
        // 触发事件,确保表单验证能够响应
        field.dispatchEvent(new Event('input', { bubbles: true }));
        field.dispatchEvent(new Event('change', { bubbles: true }));
        field.dispatchEvent(new Event('blur', { bubbles: true }));
    }

    // 从表单中读取当前值的函数
    function readFormData() {
        // 查找表单字段
        const usernameField = findFormField('username', 'user', 'login');
        const passwordField = findFormField('password', 'pass');
        const emailField = findFormField('email');
        const firstNameField = findFormField('first_name', 'firstname', 'fname', 'first name', 'name');
        const lastNameField = findFormField('last_name', 'lastname', 'lname', 'last name', 'surname');
        const addressLine1Field = findFormField('address_1', 'address1', 'address-line-1', 'address_line_1', 'address', 'street', 'line1');
        const addressLine2Field = findFormField('address_2', 'address2', 'address-line-2', 'address_line_2', 'apt', 'suite', 'line2');
        const cityField = findFormField('city', 'town');
        const stateField = findFormField('state', 'province', 'region');
        const postalCodeField = findFormField('zipcode', 'postal', 'zip', 'postcode');
        const phoneField = findFormField('phone_intl', 'phone', 'telephone', 'mobile', 'cell');

        // 读取字段值
        const formData = {
            username: usernameField ? usernameField.value : generatedData.username,
            password: passwordField ? passwordField.value : generatedData.password,
            email: emailField ? emailField.value : userFilledEmail,
            firstName: firstNameField ? firstNameField.value : generatedData.firstName,
            lastName: lastNameField ? lastNameField.value : generatedData.lastName,
            addressLine1: addressLine1Field ? addressLine1Field.value : generatedData.addressLine1,
            addressLine2: addressLine2Field ? addressLine2Field.value : generatedData.addressLine2,
            city: cityField ? cityField.value : generatedData.city,
            state: stateField ? stateField.value : generatedData.state,
            postalCode: postalCodeField ? postalCodeField.value : generatedData.postalCode,
            phone: phoneField ? phoneField.value : generatedData.phone,
            timestamp: new Date().toLocaleString(),
            id: generatedData.id || null  // 保留ID如果已存在
        };

        return formData;
    }

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

    // 初始化时添加动画样式
    addStyles();

    // 初始化UI和数据
    UI.init();
    generatedData = DataGenerator.generatePersonData();
    UI.displayCurrentData();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址