// ==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 // @downloadURL none // ==/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 = ''; 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 = '请填写邮箱后再保存'; } } html += ` `; } html += '
${formatKey(key)}: ${displayValue}
'; 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 = '

没有保存的数据

'; return; } let html = ''; // 调整登录页面按钮布局 if (!isSignInPage) { // 注册页面的清空按钮 html += `
`; } else { // 登录页面 - 左右两侧分别放置清空和导出按钮 html += `
`; } html += '
'; savedData.forEach(data => { // 显示邮箱,如果没有则显示提示文本 const emailDisplay = data.email && data.email !== "用于验证的邮箱" && data.email !== "请自行填写用于验证的邮箱" ? data.email : '未填写邮箱'; if (isSignInPage) { // 登录页面 - 更紧凑的卡片 html += `
${emailDisplay} ${data.timestamp || '未知时间'}
用户名: ${data.username}
密码: ${data.password}
`; } else { // 注册页面 - 更紧凑的卡片 html += `
${emailDisplay} ${data.timestamp || '未知时间'}
用户名: ${data.username}
密码: ${data.password}
`; } }); html += '
'; 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(); })();