首页
文章导航
留言板
友链
更多
关于
推荐
wszx博客
Search
1
cloudflare上免费部署随机地址生成器
2 阅读
2
Linux系统下常用命令【不断补充】
1 阅读
3
永久免费节点搭建!通过Cloudflare Worker部署免费的VLESS节点,4K高速,解锁Netflix、ChatGPT
1 阅读
4
套cf后 站点WAF防火墙规则设定 这2+1就够了 全能防御恶意流量攻击!
1 阅读
5
分享一些免费的 ChatGPT 镜像网站
1 阅读
默认
日常
学习
技术
登录
Search
标签搜索
cloudflare
白嫖
安装
CF
脚本
壁纸
图片
docker
Linux
Caddy
代码
哪吒
域名
节点
桌面壁纸
手机壁纸
NAT
LXC
优选
HTML
ws01
累计撰写
109
篇文章
累计收到
61
条评论
首页
栏目
默认
日常
学习
技术
页面
文章导航
留言板
友链
关于
推荐
wszx博客
搜索到
1
篇与
的结果
2025-07-15
cloudflare上免费部署随机地址生成器
cloudflare免费部署随机地址生成器github项目 这是一个基于 Cloudflare Workers 的随机地址生成器,可以生成全球多个国家的真实地址、姓名和电话号码。 本项目基于 Real-Address-Generator 做了一些样式和逻辑上的调整和优化。一、 主要功能 ,爱好者可以自己修改部署支持多个国家/地区的地址生成根据不同国家生成符合当地特色的姓名生成符合各国格式的电话号码实时地图预览地址保存和管理一键复制信息二、部署到 Cloudflare Workers1、原项目代码// 国家坐标数据 const countryCoordinates = { "US": [{ lat: 37.7749, lng: -122.4194 }, { lat: 34.0522, lng: -118.2437 }], "UK": [{ lat: 51.5074, lng: -0.1278 }, { lat: 53.4808, lng: -2.2426 }], "FR": [{ lat: 48.8566, lng: 2.3522 }, { lat: 45.7640, lng: 4.8357 }], "DE": [{ lat: 52.5200, lng: 13.4050 }, { lat: 48.1351, lng: 11.5820 }], "CN": [{ lat: 39.9042, lng: 116.4074 }, { lat: 31.2304, lng: 121.4737 }], "TW": [{ lat: 25.0330, lng: 121.5654 }, { lat: 22.6273, lng: 120.3014 }], "HK": [{ lat: 22.3193, lng: 114.1694 },{ lat: 22.3964, lng: 114.1095 }], "JP": [{ lat: 35.6895, lng: 139.6917 }, { lat: 34.6937, lng: 135.5023 }], "IN": [{ lat: 28.6139, lng: 77.2090 }, { lat: 19.0760, lng: 72.8777 }], "AU": [{ lat: -33.8688, lng: 151.2093 }, { lat: -37.8136, lng: 144.9631 }], "BR": [{ lat: -23.5505, lng: -46.6333 }, { lat: -22.9068, lng: -43.1729 }], "CA": [{ lat: 43.651070, lng: -79.347015 }, { lat: 45.501690, lng: -73.567253 }], "RU": [{ lat: 55.7558, lng: 37.6173 }, { lat: 59.9343, lng: 30.3351 }], "ZA": [{ lat: -33.9249, lng: 18.4241 }, { lat: -26.2041, lng: 28.0473 }], "MX": [{ lat: 19.4326, lng: -99.1332 }, { lat: 20.6597, lng: -103.3496 }], "KR": [{ lat: 37.5665, lng: 126.9780 }, { lat: 35.1796, lng: 129.0756 }], "IT": [{ lat: 41.9028, lng: 12.4964 }, { lat: 45.4642, lng: 9.1900 }], "ES": [{ lat: 40.4168, lng: -3.7038 }, { lat: 41.3851, lng: 2.1734 }], "TR": [{ lat: 41.0082, lng: 28.9784 }, { lat: 39.9334, lng: 32.8597 }], "SA": [{ lat: 24.7136, lng: 46.6753 }, { lat: 21.3891, lng: 39.8579 }], "AR": [{ lat: -34.6037, lng: -58.3816 }, { lat: -31.4201, lng: -64.1888 }], "EG": [{ lat: 30.0444, lng: 31.2357 }, { lat: 31.2156, lng: 29.9553 }], "NG": [{ lat: 6.5244, lng: 3.3792 }, { lat: 9.0579, lng: 7.4951 }], "ID": [{ lat: -6.2088, lng: 106.8456 }, { lat: -7.7956, lng: 110.3695 }] }; // 姓名数据 const namesByCountry = { "CN": { first: ["Li", "Wang", "Zhang", "Liu", "Chen", "Yang", "Huang", "Zhao", "Wu", "Zhou", "Xu", "Sun", "Ma", "Zhu", "Hu", "Guo", "He", "Gao", "Lin", "Zheng"], last: ["Wei", "Fang", "Na", "Xiuying", "Min", "Jing", "Li", "Qiang", "Lei", "Jun", "Yang", "Yong", "Yan", "Jie", "Tao", "Ming", "Chao", "Xiulan", "Xia", "Ping"] }, "JP": { first: ["Sato", "Suzuki", "Takahashi", "Tanaka", "Watanabe", "Ito", "Yamamoto", "Nakamura", "Kobayashi", "Kato"], last: ["Shota", "Ren", "Hina", "Yui", "Hiroto", "Sota", "Yota", "Misaki", "Nanami", "Yuto"] }, "KR": { first: ["Kim", "Lee", "Park", "Choi", "Jung", "Kang", "Jo", "Yoon", "Jang", "Lim"], last: ["Minjun", "Seojun", "Doyun", "Jiho", "Jihun", "Seoyeon", "Seoyun", "Jiwoo", "Seohyun", "Minseo"] }, "TW": { first: ["Chen", "Lin", "Huang", "Chang", "Lee", "Wang", "Wu", "Liu", "Tsai", "Yang"], last: ["Zhiming", "Jianhong", "Junjie", "Yijun", "Shufen", "Meiling", "Yating", "Jiahao", "Zhihao", "Shuhui"] }, "HK": { first: ["Chan", "Lee", "Wong", "Cheung", "Lau", "Wang", "Ng", "Cheng", "Leung", "Ho"], last: ["Chiming", "Kayan", "Junjie", "Wingsze", "Kaming", "Meiling", "Kahao", "Winger", "Chihao", "Shukfan"] }, "US": { first: ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"], last: ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Christopher"] }, "UK": { first: ["Smith", "Jones", "Williams", "Taylor", "Brown", "Davies", "Evans", "Wilson", "Thomas", "Roberts"], last: ["Oliver", "Jack", "Harry", "George", "Noah", "Charlie", "Jacob", "Oscar", "William", "Leo"] }, "FR": { first: ["Martin", "Bernard", "Dubois", "Thomas", "Robert", "Richard", "Petit", "Durand", "Leroy", "Moreau"], last: ["Lucas", "Louis", "Gabriel", "Arthur", "Jules", "Hugo", "Leo", "Adam", "Raphael", "Paul"] }, "DE": { first: ["Mueller", "Schmidt", "Schneider", "Fischer", "Weber", "Meyer", "Wagner", "Becker", "Schulz", "Hoffmann"], last: ["Ben", "Paul", "Leon", "Noah", "Luis", "Finn", "Felix", "Jonas", "Maximilian", "Henry"] }, "IT": { first: ["Rossi", "Ferrari", "Russo", "Bianchi", "Romano", "Gallo", "Costa", "Fontana", "Conti", "Esposito"], last: ["Leonardo", "Francesco", "Alessandro", "Lorenzo", "Matteo", "Andrea", "Gabriele", "Marco", "Antonio", "Giuseppe"] }, "ES": { first: ["Garcia", "Rodriguez", "Gonzalez", "Fernandez", "Lopez", "Martinez", "Sanchez", "Perez", "Martin", "Gomez"], last: ["Antonio", "Jose", "Manuel", "Francisco", "David", "Juan", "Miguel", "Javier", "Rafael", "Carlos"] }, "BR": { first: ["Silva", "Santos", "Oliveira", "Souza", "Rodrigues", "Ferreira", "Alves", "Pereira", "Lima", "Gomes"], last: ["Miguel", "Arthur", "Heitor", "Pedro", "Davi", "Gabriel", "Bernardo", "Lucas", "Matheus", "Rafael"] }, "RU": { first: ["Ivanov", "Smirnov", "Kuznetsov", "Popov", "Vasiliev", "Petrov", "Sokolov", "Mikhailov", "Fedorov", "Morozov"], last: ["Alexander", "Dmitry", "Maxim", "Ivan", "Andrey", "Mikhail", "Artem", "Daniel", "Roman", "Sergey"] }, "IN": { first: ["Kumar", "Singh", "Sharma", "Patel", "Gupta", "Shah", "Verma", "Rao", "Reddy", "Joshi"], last: ["Aarav", "Vihaan", "Vivaan", "Aditya", "Arjun", "Reyansh", "Ayaan", "Sai", "Krishna", "Ishaan"] }, "AU": { first: ["Smith", "Jones", "Williams", "Brown", "Wilson", "Taylor", "Johnson", "White", "Anderson", "Thompson"], last: ["Oliver", "William", "Jack", "Noah", "Thomas", "James", "Lucas", "Henry", "Ethan", "Alexander"] }, "CA": { first: ["Smith", "Brown", "Tremblay", "Martin", "Roy", "Wilson", "MacDonald", "Taylor", "Campbell", "Anderson"], last: ["Liam", "Noah", "Oliver", "William", "James", "Benjamin", "Lucas", "Henry", "Theodore", "Jack"] }, "MX": { first: ["Garcia", "Rodriguez", "Martinez", "Lopez", "Gonzalez", "Perez", "Sanchez", "Ramirez", "Torres", "Flores"], last: ["Santiago", "Mateo", "Sebastian", "Leonardo", "Diego", "Daniel", "Gabriel", "Adrian", "David", "Alexander"] }, "TR": { first: ["Yilmaz", "Kaya", "Demir", "Sahin", "Celik", "Yildiz", "Erdogan", "Ozturk", "Aydin", "Ozdemir"], last: ["Yusuf", "Eymen", "Ömer", "Mustafa", "Ali", "Mehmet", "Ahmet", "Emir", "Hamza", "Ibrahim"] }, "SA": { first: ["Al-Saud", "Al-Sheikh", "Al-Rashid", "Al-Qahtani", "Al-Ghamdi", "Al-Zahrani", "Al-Dossari", "Al-Shammari", "Al-Otaibi", "Al-Harbi"], last: ["Mohammed", "Abdullah", "Ahmed", "Ali", "Omar", "Ibrahim", "Khalid", "Hassan", "Fahad", "Abdul"] }, "AR": { first: ["Gonzalez", "Rodriguez", "Garcia", "Fernandez", "Lopez", "Martinez", "Perez", "Romero", "Sanchez", "Diaz"], last: ["Mateo", "Thiago", "Benjamin", "Valentino", "Santiago", "Juan", "Lucas", "Martin", "Nicolas", "Joaquin"] }, "EG": { first: ["Mohamed", "Ahmed", "Mahmoud", "Ibrahim", "Ali", "Hassan", "Hussein", "Mostafa", "Kamal", "Samir"], last: ["Omar", "Youssef", "Adam", "Malik", "Zain", "Hamza", "Kareem", "Hassan", "Ali", "Ibrahim"] }, "NG": { first: ["Okafor", "Adebayo", "Okonkwo", "Eze", "Oluwaseun", "Adegoke", "Afolabi", "Ogunleye", "Adeniyi", "Adesina"], last: ["Oluwadamilare", "Oluwatobiloba", "Ayomide", "Temitope", "Oluwaseun", "Adebayo", "Chibuike", "Chisom", "Chidi", "Obinna"] }, "ID": { first: ["Wijaya", "Kusuma", "Suryanto", "Halim", "Santoso", "Tanaka", "Wibowo", "Susanto", "Hidayat", "Putra"], last: ["Muhammad", "Ahmad", "Abdul", "Aditya", "Budi", "Dimas", "Eko", "Fajar", "Gading", "Hadi"] }, "ZA": { first: ["Nkosi", "Van der Merwe", "Botha", "Mkhize", "Khumalo", "Pretorius", "Venter", "Ndlovu", "Fourie", "Nel"], last: ["Bandile", "Themba", "Sipho", "Thabo", "Jabu", "Mandla", "Blessing", "Gift", "Lucky", "Precious"] } }; // 电话号码格式配置 const phoneFormats = { "US": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[201, 989]] }, "CN": { format: "+86 1XX-XXXX-XXXX", mobilePrefix: ["30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "50", "51", "52", "53", "55", "56", "57", "58", "59", "66", "70", "71", "72", "73", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89"] }, "JP": { format: "+81 XX-XXXX-XXXX", mobilePrefix: ["70", "80", "90"] }, "KR": { format: "+82 10-XXXX-XXXX" }, "UK": { format: "+44 7XXX XXXXXX", mobilePrefix: ["7"] }, "FR": { format: "+33 6 XX XX XX XX", mobilePrefix: ["6", "7"] }, "DE": { format: "+49 15X XXXXXXXX", mobilePrefix: ["15", "16", "17"] }, "TW": { format: "+886 9XX-XXX-XXX" }, "HK": { format: "+852 XXXX XXXX", mobilePrefix: ["5", "6", "9"] }, "AU": { format: "+61 4XX XXX XXX", mobilePrefix: ["4"] }, "CA": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[204, 989]] }, "MX": { format: "+52 1XX XXX XXXX" }, "TR": { format: "+90 5XX XXX XXXX", mobilePrefix: ["5"] }, "SA": { format: "+966 5XX XXX XXXX", mobilePrefix: ["5"] }, "AR": { format: "+54 9XX XXXX-XXXX" }, "EG": { format: "+20 1XX XXX XXXX", mobilePrefix: ["1"] }, "NG": { format: "+234 8XX XXX XXXX", mobilePrefix: ["7", "8", "9"] }, "ID": { format: "+62 8XX-XXXX-XXXX", mobilePrefix: ["8"] }, "ZA": { format: "+27 8X XXX XXXX", mobilePrefix: ["6", "7", "8"] } }; // 工具函数 function getRandomLocation(country) { const coordsArray = countryCoordinates[country]; const randomCity = coordsArray[Math.floor(Math.random() * coordsArray.length)]; const lat = randomCity.lat + (Math.random() - 0.5) * 0.1; const lng = randomCity.lng + (Math.random() - 0.5) * 0.1; return { lat, lng }; } function getRandomName(country) { if (!namesByCountry[country]) { return null; } const names = namesByCountry[country]; const firstName = names.first[Math.floor(Math.random() * names.first.length)]; const lastName = names.last[Math.floor(Math.random() * names.last.length)]; return `${firstName} ${lastName}`; } function generateAreaCode(ranges) { const range = ranges[Math.floor(Math.random() * ranges.length)]; const [min, max] = range; return Math.floor(min + Math.random() * (max - min + 1)); } function getRandomPhoneNumber(country) { const format = phoneFormats[country] || phoneFormats["US"]; let phone = format.format; if (format.areaCodeRanges) { const areaCode = generateAreaCode(format.areaCodeRanges); phone = phone.replace("XXX", areaCode); phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } else if (format.mobilePrefix) { const prefix = format.mobilePrefix[Math.floor(Math.random() * format.mobilePrefix.length)]; // 先替换前缀 if (prefix.length === 2) { phone = phone.replace(/XX/, prefix); } else { phone = phone.replace(/X/, prefix); } // 然后替换剩余的X phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } else { phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } return phone; } function isValidAddress(data) { return data && data.address && data.address.house_number && data.address.road && (data.address.city || data.address.town); } // 处理CORS请求的headers const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, HEAD, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }; // HTML 模板 const htmlContent = `<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>随机地址生成器</title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet"> <script> tailwind.config = { theme: { extend: { animation: { 'gradient': 'gradient 8s linear infinite', }, keyframes: { gradient: { '0%, 100%': { 'background-size': '200% 200%', 'background-position': 'left center' }, '50%': { 'background-size': '200% 200%', 'background-position': 'right center' } } } } } } </script> </head> <body class="bg-gradient-to-br from-blue-50 via-white to-blue-50 text-gray-800 min-h-screen font-['Noto_Sans_SC']"> <!-- 头部 --> <header class="bg-gradient-to-r from-blue-500 via-sky-500 to-blue-500 animate-gradient w-full p-6 shadow-lg"> <div class="max-w-4xl mx-auto flex items-center justify-between"> <div class="flex items-center gap-3"> <img src="https://img.freepik.com/premium-vector/minimal-location-map-icon-logo-symbol-vector-design-transparent_965979-613.jpg?w=2000" alt="Logo" class="w-12 h-12 transform hover:scale-105 transition-transform"> <h1 class="text-2xl font-bold text-white">随机地址生成器</h1> </div> <a href="https://github.com/jiangnan1224/AddressGenerator/" target="_blank" class="flex items-center gap-2 text-white hover:text-gray-200 transition-colors"> <svg viewBox="0 0 16 16" class="w-6 h-6 fill-current" aria-hidden="true"> <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path> </svg> <span class="font-medium">GitHub</span> </a> </div> </header> <!-- 主要内容 --> <main class="container mx-auto px-4 py-8 max-w-5xl"> <!-- 加载动画 --> <div id="loading" class="hidden fixed inset-0 bg-white bg-opacity-75 backdrop-blur-sm flex items-center justify-center z-50"> <div class="bg-white rounded-2xl p-8 flex flex-col items-center shadow-2xl"> <div class="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-blue-500 mb-4"></div> <div class="text-gray-800 text-lg font-medium">正在加载...</div> </div> </div> <div id="copied" class="hidden fixed top-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg z-40 transform transition-transform duration-300"> 已复制到剪贴板! </div> <!-- 国家选择 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200 mb-8"> <div class="flex flex-col sm:flex-row items-start sm:items-center gap-4"> <div class="w-full sm:w-auto flex flex-col sm:flex-row items-start sm:items-center gap-2 flex-grow"> <label for="country" class="text-blue-600 font-bold whitespace-nowrap">选择国家/地区:</label> <select id="country" onchange="changeCountry(this.value)" class="w-full bg-gray-50 border border-gray-200 rounded-xl p-3 text-gray-800 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"> </select> </div> <button onclick="generateNewAddress(document.getElementById('country').value)" class="w-full sm:w-auto bg-gradient-to-r from-blue-500 to-sky-500 hover:from-blue-600 hover:to-sky-600 text-white font-bold py-3 px-6 rounded-xl transition-all transform hover:scale-105 hover:shadow-lg focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50"> 获取新地址 </button> </div> </div> <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <!-- 左侧面板 --> <div class="space-y-6"> <!-- 信息卡片 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">个人信息</h2> <div class="space-y-4"> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">姓名:</strong><span id="name" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">性别:</strong><span id="gender" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">电话:</strong><span id="phone" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">地址:</strong><span id="address" class="ml-2"></span> </div> </div> </div> <!-- 保存按钮 --> <button onclick="saveAddress()" class="w-full bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white font-bold py-3 px-6 rounded-xl transition-all transform hover:scale-105 hover:shadow-lg focus:ring-2 focus:ring-green-500 focus:ring-opacity-50"> 保存地址 </button> </div> <!-- 右侧面板 --> <div class="space-y-6"> <!-- 地图 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">地图预览</h2> <iframe id="map" class="w-full h-[400px] rounded-xl border border-gray-200"></iframe> </div> </div> </div> <!-- 已保存的地址表格 --> <div class="mt-8 bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">已保存的地址</h2> <div class="overflow-x-auto"> <table class="w-full border-collapse" id="savedAddressesTable"> <thead> <tr class="bg-gradient-to-r from-blue-500 to-sky-500 text-white"> <th class="p-4 text-left rounded-tl-lg">姓名</th> <th class="p-4 text-left">性别</th> <th class="p-4 text-left">电话号码</th> <th class="p-4 text-left">地址</th> <th class="p-4 text-left">备注</th> <th class="p-4 text-left rounded-tr-lg">操作</th> </tr> </thead> <tbody></tbody> </table> </div> </div> </main> <!-- 页脚 --> <footer class="text-center py-8 text-gray-600 text-sm mt-8 bg-gray-50 border-t border-gray-200"> <p class="max-w-4xl mx-auto px-4"> All right reserved <a href="https://github.com/jiangnan1224/AddressGenerator/" target="_blank" class="inline-flex items-center hover:text-blue-600 transition-colors"> <img src="https://pic.imgdb.cn/item/66e7ab36d9c307b7e9cefd24.png" alt="GitHub" class="w-5 h-5 ml-1"> </a> </p> </footer> <script> // 国家数据 const countries = [ { name: "美国", code: "US" }, { name: "英国", code: "UK" }, { name: "法国", code: "FR" }, { name: "德国", code: "DE" }, { name: "中国", code: "CN" }, { name: "中国台湾", code: "TW" }, { name: "中国香港", code: "HK" }, { name: "日本", code: "JP" }, { name: "印度", code: "IN" }, { name: "澳大利亚", code: "AU" }, { name: "巴西", code: "BR" }, { name: "加拿大", code: "CA" }, { name: "俄罗斯", code: "RU" }, { name: "南非", code: "ZA" }, { name: "墨西哥", code: "MX" }, { name: "韩国", code: "KR" }, { name: "意大利", code: "IT" }, { name: "西班牙", code: "ES" }, { name: "土耳其", code: "TR" }, { name: "沙特阿拉伯", code: "SA" }, { name: "阿根廷", code: "AR" }, { name: "埃及", code: "EG" }, { name: "尼日利亚", code: "NG" }, { name: "印度尼西亚", code: "ID" } ]; // 初始化国家选择下拉框 function initCountrySelect() { const select = document.getElementById('country'); countries.forEach(country => { const option = document.createElement('option'); option.value = country.code; option.textContent = country.name; select.appendChild(option); }); } // 复制到剪贴板 function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { const copied = document.getElementById('copied'); copied.classList.remove('hidden'); copied.classList.add('translate-y-0'); copied.classList.remove('translate-y-[-100%]'); setTimeout(() => { copied.classList.add('translate-y-[-100%]'); copied.classList.remove('translate-y-0'); setTimeout(() => { copied.classList.add('hidden'); }, 300); }, 2000); }); } // 显示/隐藏加载动画 function toggleLoading(show) { const loading = document.getElementById('loading'); if (show) { loading.classList.remove('hidden'); } else { loading.classList.add('hidden'); } } // 更改国家 function changeCountry(country) { toggleLoading(true); generateNewAddress(country); } // 保存地址 function saveAddress() { const note = prompt('请输入备注(可以留空)') || ''; const savedAddresses = JSON.parse(localStorage.getItem('savedAddresses') || '[]'); const newEntry = { note: note, name: document.getElementById('name').textContent, gender: document.getElementById('gender').textContent, phone: document.getElementById('phone').textContent, address: document.getElementById('address').textContent }; savedAddresses.push(newEntry); localStorage.setItem('savedAddresses', JSON.stringify(savedAddresses)); renderSavedAddresses(); } // 渲染保存的地址 function renderSavedAddresses() { const savedAddresses = JSON.parse(localStorage.getItem('savedAddresses') || '[]'); const tbody = document.querySelector('#savedAddressesTable tbody'); tbody.innerHTML = ''; savedAddresses.forEach((entry, index) => { const row = tbody.insertRow(); row.className = 'border-t border-gray-200 hover:bg-gray-50 transition-colors'; const cells = ['name', 'gender', 'phone', 'address', 'note', '']; cells.forEach((cell, i) => { const td = row.insertCell(); td.className = 'p-4'; if (i === cells.length - 1) { const deleteBtn = document.createElement('button'); deleteBtn.textContent = '删除'; deleteBtn.className = 'bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition-all transform hover:scale-105 focus:ring-2 focus:ring-red-500 focus:ring-opacity-50'; deleteBtn.onclick = () => { if (confirm('确定要删除这条记录吗?')) { savedAddresses.splice(index, 1); localStorage.setItem('savedAddresses', JSON.stringify(savedAddresses)); renderSavedAddresses(); } }; td.appendChild(deleteBtn); } else { td.textContent = entry[cell]; } }); }); } // 生成新地址 async function generateNewAddress(country) { if (!country) { country = document.getElementById('country').value; } toggleLoading(true); try { const response = await fetch(\`\${window.location.href}api?country=\${country}\`); const data = await response.json(); if (data.error) { alert(data.error); return; } document.getElementById('name').textContent = data.name; document.getElementById('gender').textContent = data.gender; document.getElementById('phone').textContent = data.phone; document.getElementById('address').textContent = data.address; // 更新地图 document.getElementById('map').src = \`https://www.google.com/maps?q=\${encodeURIComponent(data.address)}&output=embed\`; } catch (error) { console.error('Error fetching address:', error); alert('获取地址时发生错误,请重试'); } finally { toggleLoading(false); } } // 页面加载时初始化 window.onload = function() { initCountrySelect(); generateNewAddress(); renderSavedAddresses(); }; </script> </body> </html>`; async function handleRequest(request) { const url = new URL(request.url); const path = url.pathname; // 处理 API 请求 if (path === '/api') { // 原有的 API 处理逻辑 return handleApiRequest(request); } // 处理根路径请求,返回 HTML 页面 return new Response(htmlContent, { headers: { 'Content-Type': 'text/html;charset=UTF-8', ...corsHeaders } }); } // 将原有的处理逻辑移到单独的函数中 async function handleApiRequest(request) { if (request.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } if (request.method !== 'GET') { return new Response('Method not allowed', { status: 405 }); } const url = new URL(request.url); const country = url.searchParams.get('country') || 'US'; if (!countryCoordinates[country]) { return new Response(JSON.stringify({ error: 'Invalid country code' }), { status: 400, headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } let attempts = 0; const maxAttempts = 20; while (attempts < maxAttempts) { try { const location = getRandomLocation(country); const apiUrl = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${location.lat}&lon=${location.lng}&zoom=18&addressdetails=1`; const response = await fetch(apiUrl, { headers: { 'User-Agent': 'Cloudflare Worker Random Address Generator' } }); const data = await response.json(); if (isValidAddress(data)) { let city = data.address.city || data.address.town || ''; city = city.split(';')[0].trim(); const address = `${data.address.house_number} ${data.address.road}, ${city}, ${data.address.postcode || ''}, ${country}`.replace(/\s+/g, ' ').trim(); const name = getRandomName(country); const gender = Math.random() > 0.5 ? 'Male' : 'Female'; const phone = getRandomPhoneNumber(country); const result = { name, gender, phone, address, coordinates: { lat: location.lat, lng: location.lng } }; return new Response(JSON.stringify(result), { headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } attempts++; if (attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 100)); } } catch (error) { attempts++; if (attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 100)); } } } return new Response(JSON.stringify({ error: 'Failed to generate valid address after multiple attempts' }), { status: 500, headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } // 注册事件监听器 addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); {dotted startColor="#ff6c6c" endColor="#1989fa"/}2、修改后的代码,各有所好,当然也可以找一下其它人修改的代码2025年07月16日更新,界面调整,添加多个国家和地区// 国家坐标数据 const countryCoordinates = { "US": [{ lat: 37.7749, lng: -122.4194 }, { lat: 34.0522, lng: -118.2437 }, { lat: 32.7767, lng: -96.7970 }, { lat: 41.8781, lng: -87.6298 }, { lat: 29.7604, lng: -95.3698 }, { lat: 33.4484, lng: -112.0740 }, { lat: 39.9526, lng: -75.1652 }, { lat: 29.4241, lng: -98.4936 }, { lat: 32.7157, lng: -117.1611 }, { lat: 47.6062, lng: -122.3321 }], "NY US": [{ lat: 40.7128, lng: -74.0060 }], "California US": [{ lat: 34.0522, lng: -118.2437 }], "Texas US": [{ lat: 32.7767, lng: -96.7970 }], "CA US": [{ lat: 37.3382, lng: -121.8863 }], "Illinois US": [{ lat: 41.8781, lng: -87.6298 }], // 添加的城市坐标:休斯敦、菲尼克斯、费城、圣安东尼奥、圣地亚哥、西雅图 "TX US": [{ lat: 29.7604, lng: -95.3698 }], "Arizona US": [{ lat: 33.4484, lng: -112.0740 }], "Pennsylvania US": [{ lat: 39.9526, lng: -75.1652 }], "Tx US": [{ lat: 29.4241, lng: -98.4936 }], "Ca US": [{ lat: 32.7157, lng: -117.1611 }], "Washington US": [{ lat: 47.6062, lng: -122.3321 }], "UK": [{ lat: 51.5074, lng: -0.1278 }, { lat: 53.4808, lng: -2.2426 }], "FR": [{ lat: 48.8566, lng: 2.3522 }, { lat: 45.7640, lng: 4.8357 }, { lat: 43.2965, lng: 5.3698 }], "DE": [{ lat: 52.5200, lng: 13.4050 }, { lat: 48.1351, lng: 11.5820 }], "CN": [{ lat: 39.9042, lng: 116.4074 }, { lat: 31.2304, lng: 121.4737 }], "TW": [{ lat: 25.0330, lng: 121.5654 }, { lat: 22.6273, lng: 120.3014 }], "HK": [{ lat: 22.3193, lng: 114.1694 },{ lat: 22.3964, lng: 114.1095 }], "JP": [{ lat: 35.6895, lng: 139.6917 }, { lat: 34.6937, lng: 135.5023 }], "IN": [{ lat: 28.6139, lng: 77.2090 }, { lat: 19.0760, lng: 72.8777 }], "AU": [{ lat: -33.8688, lng: 151.2093 }, { lat: -37.8136, lng: 144.9631 }], "BR": [{ lat: -23.5505, lng: -46.6333 }, { lat: -22.9068, lng: -43.1729 }], "CA": [{ lat: 43.651070, lng: -79.347015 }, { lat: 45.501690, lng: -73.567253 }], "RU": [{ lat: 55.7558, lng: 37.6173 }, { lat: 59.9343, lng: 30.3351 }], "ZA": [{ lat: -33.9249, lng: 18.4241 }, { lat: -26.2041, lng: 28.0473 }], "MX": [{ lat: 19.4326, lng: -99.1332 }, { lat: 20.6597, lng: -103.3496 }], "KR": [{ lat: 37.5665, lng: 126.9780 }, { lat: 35.1796, lng: 129.0756 }], "IT": [{ lat: 41.9028, lng: 12.4964 }, { lat: 45.4642, lng: 9.1900 }], "ES": [{ lat: 40.4168, lng: -3.7038 }, { lat: 41.3851, lng: 2.1734 }], "TR": [{ lat: 41.0082, lng: 28.9784 }, { lat: 39.9334, lng: 32.8597 }], "SA": [{ lat: 24.7136, lng: 46.6753 }, { lat: 21.3891, lng: 39.8579 }], "AR": [{ lat: -34.6037, lng: -58.3816 }, { lat: -31.4201, lng: -64.1888 }], "EG": [{ lat: 30.0444, lng: 31.2357 }, { lat: 31.2156, lng: 29.9553 }], "NG": [{ lat: 6.5244, lng: 3.3792 }, { lat: 9.0579, lng: 7.4951 }], "ID": [{ lat: -6.2088, lng: 106.8456 }, { lat: -7.7956, lng: 110.3695 }], "VN": [{ lat: 21.0285, lng: 105.8048 }, { lat: 10.7626, lng: 106.6602 }], // 添加越南坐标数据 // 新增城市坐标 "Berlin DE": [{ lat: 52.5200, lng: 13.4050 }], "Bavaria DE": [{ lat: 48.1351, lng: 11.5820 }], "Île-de-France FR": [{ lat: 48.8566, lng: 2.3522 }], "Provence-Alpes-Côte d'Azur FR": [{ lat: 43.2965, lng: 5.3698 }], "London UK": [{ lat: 51.5074, lng: -0.1278 }], "Seoul KR": [{ lat: 37.5665, lng: 126.9780 }], "Ontario CA": [{ lat: 43.651070, lng: -79.347015 }], "Comunidad de Madrid ES": [{ lat: 40.4168, lng: -3.7038 }], "Cataluña ES": [{ lat: 41.3851, lng: 2.1734 }], "Tokyo JP": [{ lat: 35.6895, lng: 139.6917 }], "Osaka JP": [{ lat: 34.6937, lng: 135.5023 }], }; // 姓名数据 const namesByCountry = { "US": { first: ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"], last: ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Christopher"] }, "CN": { first: ["李", "王", "张", "刘", "陈", "杨", "黄", "赵", "吴", "周", "孙", "苏", "马", "朱", "候", "郭", "黑", "高", "林", "钱", "冯", "卫", "蒋", "许", "吕", "施", "曹", "严", "魏", "陶", "方", "雷"], last: ["力", "斌", "那", "真", "杰", "京", "丽", "晴", "来", "东", "勇", "仕", "云", "洁", "山", "伟", "明", "亮", "刚", "飞", "英", "兴", "浩", "曙光", "平", "志远", "志珍", "第一", "建国", "玉仙", "现红", "瑞山", "一山", "新丽", "思思", "青凤", "秀美"] }, "JP": { first: ["Sato", "Suzuki", "Takahashi", "Tanaka", "Watanabe", "Ito", "Yamamoto", "Nakamura", "Kobayashi", "Kato"], last: ["Shota", "Ren", "Hina", "Yui", "Hiroto", "Sota", "Yota", "Misaki", "Nanami", "Yuto"] }, "KR": { first: ["Kim", "Lee", "Park", "Choi", "Jung", "Kang", "Jo", "Yoon", "Jang", "Lim"], last: ["Minjun", "Seojun", "Doyun", "Jiho", "Jihun", "Seoyeon", "Seoyun", "Jiwoo", "Seohyun", "Minseo"] }, "TW": { first: ["Chen", "Lin", "Huang", "Chang", "Lee", "Wang", "Wu", "Liu", "Tsai", "Yang"], last: ["Zhiming", "Jianhong", "Junjie", "Yijun", "Shufen", "Meiling", "Yating", "Jiahao", "Zhihao", "Shuhui"] }, "HK": { first: ["Chan", "Lee", "Wong", "Cheung", "Lau", "Wang", "Ng", "Cheng", "Leung", "Ho"], last: ["Chiming", "Kayan", "Junjie", "Wingsze", "Kaming", "Meiling", "Kahao", "Winger", "Chihao", "Shukfan"] }, "UK": { first: ["Smith", "Jones", "Williams", "Taylor", "Brown", "Davies", "Evans", "Wilson", "Thomas", "Roberts"], last: ["Oliver", "Jack", "Harry", "George", "Noah", "Charlie", "Jacob", "Oscar", "William", "Leo"] }, "FR": { first: ["Martin", "Bernard", "Dubois", "Thomas", "Robert", "Richard", "Petit", "Durand", "Leroy", "Moreau"], last: ["Lucas", "Louis", "Gabriel", "Arthur", "Jules", "Hugo", "Leo", "Adam", "Raphael", "Paul"] }, "DE": { first: ["Mueller", "Schmidt", "Schneider", "Fischer", "Weber", "Meyer", "Wagner", "Becker", "Schulz", "Hoffmann"], last: ["Ben", "Paul", "Leon", "Noah", "Luis", "Finn", "Felix", "Jonas", "Maximilian", "Henry"] }, "IT": { first: ["Rossi", "Ferrari", "Russo", "Bianchi", "Romano", "Gallo", "Costa", "Fontana", "Conti", "Esposito"], last: ["Leonardo", "Francesco", "Alessandro", "Lorenzo", "Matteo", "Andrea", "Gabriele", "Marco", "Antonio", "Giuseppe"] }, "ES": { first: ["Garcia", "Rodriguez", "Gonzalez", "Fernandez", "Lopez", "Martinez", "Sanchez", "Perez", "Martin", "Gomez"], last: ["Antonio", "Jose", "Manuel", "Francisco", "David", "Juan", "Miguel", "Javier", "Rafael", "Carlos"] }, "BR": { first: ["Silva", "Santos", "Oliveira", "Souza", "Rodrigues", "Ferreira", "Alves", "Pereira", "Lima", "Gomes"], last: ["Miguel", "Arthur", "Heitor", "Pedro", "Davi", "Gabriel", "Bernardo", "Lucas", "Matheus", "Rafael"] }, "RU": { first: ["Ivanov", "Smirnov", "Kuznetsov", "Popov", "Vasiliev", "Petrov", "Sokolov", "Mikhailov", "Fedorov", "Morozov"], last: ["Alexander", "Dmitry", "Maxim", "Ivan", "Andrey", "Mikhail", "Artem", "Daniel", "Roman", "Sergey"] }, "IN": { first: ["Kumar", "Singh", "Sharma", "Patel", "Gupta", "Shah", "Verma", "Rao", "Reddy", "Joshi"], last: ["Aarav", "Vihaan", "Vivaan", "Aditya", "Arjun", "Reyansh", "Ayaan", "Sai", "Krishna", "Ishaan"] }, "AU": { first: ["Smith", "Jones", "Williams", "Brown", "Wilson", "Taylor", "Johnson", "White", "Anderson", "Thompson"], last: ["Oliver", "William", "Jack", "Noah", "Thomas", "James", "Lucas", "Henry", "Ethan", "Alexander"] }, "CA": { first: ["Smith", "Brown", "Tremblay", "Martin", "Roy", "Wilson", "MacDonald", "Taylor", "Campbell", "Anderson"], last: ["Liam", "Noah", "Oliver", "William", "James", "Benjamin", "Lucas", "Henry", "Theodore", "Jack"] }, "MX": { first: ["Garcia", "Rodriguez", "Martinez", "Lopez", "Gonzalez", "Perez", "Sanchez", "Ramirez", "Torres", "Flores"], last: ["Santiago", "Mateo", "Sebastian", "Leonardo", "Diego", "Daniel", "Gabriel", "Adrian", "David", "Alexander"] }, "TR": { first: ["Yilmaz", "Kaya", "Demir", "Sahin", "Celik", "Yildiz", "Erdogan", "Ozturk", "Aydin", "Ozdemir"], last: ["Yusuf", "Eymen", "Ömer", "Mustafa", "Ali", "Mehmet", "Ahmet", "Emir", "Hamza", "Ibrahim"] }, "SA": { first: ["Al-Saud", "Al-Sheikh", "Al-Rashid", "Al-Qahtani", "Al-Ghamdi", "Al-Zahrani", "Al-Dossari", "Al-Shammari", "Al-Otaibi", "Al-Harbi"], last: ["Mohammed", "Abdullah", "Ahmed", "Ali", "Omar", "Ibrahim", "Khalid", "Hassan", "Fahad", "Abdul"] }, "AR": { first: ["Gonzalez", "Rodriguez", "Garcia", "Fernandez", "Lopez", "Martinez", "Perez", "Romero", "Sanchez", "Diaz"], last: ["Mateo", "Thiago", "Benjamin", "Valentino", "Santiago", "Juan", "Lucas", "Martin", "Nicolas", "Joaquin"] }, "EG": { first: ["Mohamed", "Ahmed", "Mahmoud", "Ibrahim", "Ali", "Hassan", "Hussein", "Mostafa", "Kamal", "Samir"], last: ["Omar", "Youssef", "Adam", "Malik", "Zain", "Hamza", "Kareem", "Hassan", "Ali", "Ibrahim"] }, "NG": { first: ["Okafor", "Adebayo", "Okonkwo", "Eze", "Oluwaseun", "Adegoke", "Afolabi", "Ogunleye", "Adeniyi", "Adesina"], last: ["Oluwadamilare", "Oluwatobiloba", "Ayomide", "Temitope", "Oluwaseun", "Adebayo", "Chibuike", "Chisom", "Chidi", "Obinna"] }, "ID": { first: ["Wijaya", "Kusuma", "Suryanto", "Halim", "Santoso", "Tanaka", "Wibowo", "Susanto", "Hidayat", "Putra"], last: ["Muhammad", "Ahmad", "Abdul", "Aditya", "Budi", "Dimas", "Eko", "Fajar", "Gading", "Hadi"] }, "ZA": { first: ["Nkosi", "Van der Merwe", "Botha", "Mkhize", "Khumalo", "Pretorius", "Venter", "Ndlovu", "Fourie", "Nel"], last: ["Bandile", "Themba", "Sipho", "Thabo", "Jabu", "Mandla", "Blessing", "Gift", "Lucky", "Precious"] }, "VN": { first: ["Nguyen", "Tran", "Le", "Pham", "Hoang", "Vu", "Do", "Dao", "Bui", "Dang"], last: ["Van", "Minh", "Thanh", "Ngoc", "Huu", "Quoc", "Xuan", "Duc", "Tuan", "Khanh"] } }; // 电话号码格式配置 const phoneFormats = { "US": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[201, 989]] }, "CN": { format: "+86 1XX-XXXX-XXXX", mobilePrefix: ["30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "50", "51", "52", "53", "55", "56", "57", "58", "59", "66", "70", "71", "72", "73", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89"] }, "JP": { format: "+81 XX-XXXX-XXXX", mobilePrefix: ["70", "80", "90"] }, "KR": { format: "+82 10-XXXX-XXXX" }, "UK": { format: "+44 7XXX XXXXXX", mobilePrefix: ["7"] }, "FR": { format: "+33 6 XX XX XX XX", mobilePrefix: ["6", "7"] }, "DE": { format: "+49 15X XXXXXXXX", mobilePrefix: ["15", "16", "17"] }, "TW": { format: "+886 9XX-XXX-XXX" }, "HK": { format: "+852 XXXX XXXX", mobilePrefix: ["5", "6", "9"] }, "AU": { format: "+61 4XX XXX XXX", mobilePrefix: ["4"] }, "CA": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[204, 989]] }, "MX": { format: "+52 1XX XXX XXXX" }, "TR": { format: "+90 5XX XXX XXXX", mobilePrefix: ["5"] }, "SA": { format: "+966 5XX XXX XXXX", mobilePrefix: ["5"] }, "AR": { format: "+54 9XX XXXX-XXXX" }, "EG": { format: "+20 1XX XXX XXXX", mobilePrefix: ["1"] }, "NG": { format: "+234 8XX XXX XXXX", mobilePrefix: ["7", "8", "9"] }, "ID": { format: "+62 8XX-XXXX-XXXX", mobilePrefix: ["8"] }, "ZA": { format: "+27 8X XXX XXXX", mobilePrefix: ["6", "7", "8"] }, "VN": { format: "+84 9X XXX XXXX", mobilePrefix: ["9", "8"] } }; // 新增加的所有美国地区别名都指向同一个 US 数据 namesByCountry["NY US"] = namesByCountry["US"]; namesByCountry["California US"] = namesByCountry["US"]; namesByCountry["Texas US"] = namesByCountry["US"]; namesByCountry["CA US"] = namesByCountry["US"]; namesByCountry["Illinois US"] = namesByCountry["US"]; namesByCountry["TX US"] = namesByCountry["US"]; namesByCountry["Arizona US"] = namesByCountry["US"]; namesByCountry["Pennsylvania US"] = namesByCountry["US"]; namesByCountry["Tx US"] = namesByCountry["US"]; namesByCountry["Ca US"] = namesByCountry["US"]; namesByCountry["Washington US"] = namesByCountry["US"]; namesByCountry["Berlin DE"] = namesByCountry["DE"]; namesByCountry["Bavaria DE"] = namesByCountry["DE"]; namesByCountry["Île-de-France FR"] = namesByCountry["FR"]; namesByCountry["Provence-Alpes-Côte d'Azur FR"] = namesByCountry["FR"]; namesByCountry["London UK"] = namesByCountry["UK"]; namesByCountry["Seoul KR"] = namesByCountry["KR"]; namesByCountry["Ontario CA"] = namesByCountry["CA"]; namesByCountry["Comunidad de Madrid ES"] = namesByCountry["ES"]; namesByCountry["Cataluña ES"] = namesByCountry["ES"]; namesByCountry["Tokyo JP"] = namesByCountry["JP"]; namesByCountry["Osaka JP"] = namesByCountry["JP"]; // 新增加的美国所有电话别名都指向同一个 US 数据 phoneFormats["NY US"] = phoneFormats["US"]; phoneFormats["California US"] = phoneFormats["US"]; phoneFormats["Texas US"] = phoneFormats["US"]; phoneFormats["CA US"] = phoneFormats["US"]; phoneFormats["Illinois US"] = phoneFormats["US"]; phoneFormats["TX US"] = phoneFormats["US"]; phoneFormats["Arizona US"] = phoneFormats["US"]; phoneFormats["Pennsylvania US"] = phoneFormats["US"]; phoneFormats["Tx US"] = phoneFormats["US"]; phoneFormats["Ca US"] = phoneFormats["US"]; phoneFormats["Washington US"] = phoneFormats["US"]; phoneFormats["Berlin DE"] = phoneFormats["DE"]; phoneFormats["Bavaria DE"] = phoneFormats["DE"]; phoneFormats["Île-de-France FR"] = phoneFormats["FR"]; phoneFormats["Provence-Alpes-Côte d'Azur FR"] = phoneFormats["FR"]; phoneFormats["London UK"] = phoneFormats["UK"]; phoneFormats["Seoul KR"] = phoneFormats["KR"]; phoneFormats["Ontario CA"] = phoneFormats["CA"]; phoneFormats["Comunidad de Madrid ES"] = phoneFormats["ES"]; phoneFormats["Cataluña ES"] = phoneFormats["ES"]; phoneFormats["Tokyo JP"] = phoneFormats["JP"]; phoneFormats["Osaka JP"] = phoneFormats["JP"]; // 工具函数 function getRandomLocation(country) { const coordsArray = countryCoordinates[country]; const randomCity = coordsArray[Math.floor(Math.random() * coordsArray.length)]; const lat = randomCity.lat + (Math.random() - 0.5) * 0.1; const lng = randomCity.lng + (Math.random() - 0.5) * 0.1; return { lat, lng }; } function getRandomName(country) { if (!namesByCountry[country]) { return null; } const names = namesByCountry[country]; const firstName = names.first[Math.floor(Math.random() * names.first.length)]; const lastName = names.last[Math.floor(Math.random() * names.last.length)]; return `${firstName} ${lastName}`; } function generateAreaCode(ranges) { const range = ranges[Math.floor(Math.random() * ranges.length)]; const [min, max] = range; return Math.floor(min + Math.random() * (max - min + 1)); } function getRandomPhoneNumber(country) { const format = phoneFormats[country] || phoneFormats["US"]; let phone = format.format; if (format.areaCodeRanges) { const areaCode = generateAreaCode(format.areaCodeRanges); phone = phone.replace("XXX", areaCode); phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } else if (format.mobilePrefix) { const prefix = format.mobilePrefix[Math.floor(Math.random() * format.mobilePrefix.length)]; // 先替换前缀 if (prefix.length === 2) { phone = phone.replace(/XX/, prefix); } else { phone = phone.replace(/X/, prefix); } // 然后替换剩余的X phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } else { phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } return phone; } function isValidAddress(data) { return data && data.address && data.address.house_number && data.address.road && (data.address.city || data.address.town); } // 处理CORS请求的headers const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, HEAD, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }; // HTML 模板 const htmlContent = `<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>随机地址生成器</title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet"> <script> tailwind.config = { theme: { extend: { animation: { 'gradient': 'gradient 8s linear infinite', }, keyframes: { gradient: { '0%, 100%': { 'background-size': '200% 200%', 'background-position': 'left center' }, '50%': { 'background-size': '200% 200%', 'background-position': 'right center' } } } } } } </script> </head> <link rel="shortcut icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2280%22>🌐</text></svg>"> <body class="bg-gradient-to-br from-blue-50 via-white to-blue-50 text-gray-800 min-h-screen font-['Noto_Sans_SC']"> <!-- 头部 --> <header class="bg-gradient-to-r from-blue-500 via-sky-500 to-blue-500 animate-gradient w-full p-6 shadow-lg"> <div class="max-w-4xl mx-auto flex items-center justify-between"> <div class="flex items-center gap-3"> <h1 class="text-2xl font-bold text-white">随机地址生成器</h1> </div> <div class="flex items-center gap-3"> <a href="/" target="_blank" class="flex items-center gap-2 text-white hover:text-gray-200 transition-colors"> <svg viewBox="0 0 16 16" class="w-6 h-6 fill-current" aria-hidden="true"> <img src="https://img.freepik.com/premium-vector/minimal-location-map-icon-logo-symbol-vector-design-transparent_965979-613.jpg?w=2000" alt="Logo" class="w-8 h-8 transform hover:scale-105 transition-transform"> </svg> </a> <a href="/about" class="flex items-center gap-2 text-white hover:text-gray-200 transition-colors"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle" viewBox="0 0 16 16"> <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/> <path d="m8.93 6.588-2.29.287-.082.38.45.083c.296.07.366.177.246.475l-.136.283-.14.064c-.296.136-.494.397-.56.745-.107 1.044.44 1.43 1.234 1.43.46.002.832-.166 1.06-.432.246-.28.334-.677.256-1.176-.09-.564-.426-.977-.977-.977-.642 0-.962.514-.962 1.176 0 .242.047.466.126.652.126.309.34.564.626.652.296.09.662.034.962-.126.296-.16.494-.432.56-.744.107-.564-.246-1.098-.832-1.098-.426 0-.764.29-.962.652-.107.19-.186.408-.246.652-.06.244-.082.49-.082.744 0 1.134.732 2.042 1.634 2.042.902 0 1.634-.908 1.634-2.042 0-1.134-.732-2.042-1.634-2.042zm-.634 5.5c-.344 0-.6-.256-.6-.588 0-.332.256-.588.6-.588.344 0 .6.256.6.588 0 .332-.256.588-.6.588z"/> </svg> <span class="font-medium">关于</span> </a> </div> </div> </header> <!-- 关于页面内容 --> <div id="about" class="hidden max-w-4xl mx-auto px-4 py-8"> <div class="bg-white rounded-2xl shadow-xl p-8 border border-gray-200"> <h2 class="text-2xl font-bold mb-6 text-blue-600">关于本项目</h2> <div class="prose max-w-none"> <p class="mb-4">随机地址生成器是一个实用工具,可以帮助用户快速生成大多数常用国家和地区的随机地址信息【根据需要,国家和地区不断完善中】。该工具适用于测试、开发以及其他需要模拟地址数据的场景。</p> <p class="mb-4">本项目使用 Cloudflare Workers 技术构建,结合 OpenStreetMap 的地理编码服务,能够实时生成准确的地址信息。通过简单的界面操作,您可以轻松获取不同国家的地址、电话号码和个人信息。</p> <h3 class="text-xl font-semibold mt-6 mb-3 text-blue-600">主要功能</h3> <ul class="list-disc pl-6 space-y-2 mb-4"> <li>支持多个国家和地区的地址生成</li> <li>自动生成姓名、性别、电话号码等个人信息</li> <li>技术有限,英国、日本等一些国家的邮编,『地址中倒数第2项提取』</li> <li>集成地图预览功能</li> <li>支持保存常用地址</li> <li>响应式设计适配各种设备</li> </ul> <h3 class="text-xl font-semibold mt-6 mb-3 text-blue-600">技术特点</h3> <ul class="list-disc pl-6 space-y-2 mb-4"> <li>基于 Cloudflare Workers 构建,实现无服务器架构</li> <li>使用 Tailwind CSS 实现现代化 UI 设计</li> <li>集成 OpenStreetMap 地理编码 API</li> <li>前端完全静态化,无需后端数据库支持</li> <li>本地存储保存历史记录</li> </ul> <h3 class="text-xl font-semibold mt-6 mb-3 text-blue-600">使用说明</h3> <p class="mb-4">选择国家或地区后点击“获取新地址”按钮即可生成随机地址信息。您可以通过点击各项信息将其复制到剪贴板,也可以点击“保存地址”按钮将当前地址保存到本地浏览器。</p> <p class="mb-4">在保存的地址列表中,您可以查看所有已保存的地址,并可随时删除不需要的记录。</p> <h3 class="text-xl font-semibold mt-6 mb-3 text-blue-600">联系方式</h3> <p>如有任何问题或建议,请访问我们的<a href="https://www.199881.xyz/" target="_blank" class="text-blue-600 hover:underline">官方网站</a>或通过 GitHub 联系我们。</p> </div> </div> </div> <!-- 主要内容 --> <main id="main-content" class="container mx-auto px-4 py-8 max-w-5xl"> <!-- 加载动画 --> <div id="loading" class="hidden fixed inset-0 bg-white bg-opacity-75 backdrop-blur-sm flex items-center justify-center z-50"> <div class="bg-white rounded-2xl p-8 flex flex-col items-center shadow-2xl"> <div class="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-blue-500 mb-4"></div> <div class="text-gray-800 text-lg font-medium">正在加载...</div> </div> </div> <div id="copied" class="hidden fixed top-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg z-40 transform transition-transform duration-300"> 已复制到剪贴板! </div> <!-- 国家选择 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200 mb-8"> <div class="flex flex-col sm:flex-row items-start sm:items-center gap-4"> <div class="w-full sm:w-auto flex flex-col sm:flex-row items-start sm:items-center gap-2 flex-grow"> <label for="country" class="text-blue-600 font-bold whitespace-nowrap">选择国家/地区:</label> <select id="country" onchange="changeCountry(this.value)" class="w-full bg-gray-50 border border-gray-200 rounded-xl p-3 text-gray-800 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"> </select> </div> <button onclick="generateNewAddress(document.getElementById('country').value)" class="w-full sm:w-auto bg-gradient-to-r from-blue-500 to-sky-500 hover:from-blue-600 hover:to-sky-600 text-white font-bold py-3 px-6 rounded-xl transition-all transform hover:scale-105 hover:shadow-lg focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50"> 获取新地址 </button> </div> </div> <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <!-- 左侧面板 --> <div class="space-y-2"> <!-- 信息卡片 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">个人信息</h2> <div class="space-y-2"> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">姓名:</strong><span id="name" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">性别:</strong><span id="gender" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">电话:</strong><span id="phone" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">邮编:</strong><span id="postcode" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">地址:</strong><span id="address" class="ml-2"></span> </div> </div> </div> <!-- 保存按钮 --> <button onclick="saveAddress()" class="w-full bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white font-bold py-3 px-6 rounded-xl transition-all transform hover:scale-105 hover:shadow-lg focus:ring-2 focus:ring-green-500 focus:ring-opacity-50"> 保存地址 </button> </div> <!-- 右侧面板 --> <div class="space-y-2"> <!-- 地图 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">地图预览</h2> <iframe id="map" class="w-full h-[372px] rounded-xl border border-gray-200"></iframe> </div> </div> </div> <!-- 已保存的地址表格 --> <div class="mt-8 bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">已保存的地址</h2> <div class="overflow-x-auto"> <table class="w-full border-collapse" id="savedAddressesTable"> <thead> <tr class="bg-gradient-to-r from-blue-500 to-sky-500 text-white"> <th class="p-4 text-left rounded-tl-lg">姓名</th> <th class="p-4 text-left">性别</th> <th class="p-4 text-left">电话</th> <th class="p-4 text-left">地址</th> <th class="p-4 text-left">备注</th> <th class="p-4 text-left rounded-tr-lg">操作</th> </tr> </thead> <tbody></tbody> </table> </div> </div> </main> <!-- 页脚 --> <footer class="text-center py-8 text-gray-600 text-sm mt-8 bg-gray-50 border-t border-gray-200"> <p class="max-w-4xl mx-auto px-4"> 总访问量 <span id="busuanzi_site_pv"></span> 次 | <span id="timeDate">载入天数...</span> | <a href="https://boke.199881.xyz/" target="_blank"> <span style="color: blue;">博客 | <a href="https://www.199881.xyz/" target="_blank"> <span style="color: green;">导航 <a href="https://github.com/jiangnan1224/AddressGenerator/" target="_blank" class="inline-flex items-center hover:text-blue-600 transition-colors"> <img src="https://pic.imgdb.cn/item/66e7ab36d9c307b7e9cefd24.png" alt="GitHub" class="w-5 h-5 ml-1"> </a> <script language="javascript"> var now = new Date(); function createtime(){ var grt= new Date("04/23/2025 00:00:00");/*---这里是网站的启用时间--*/ now.setTime(now.getTime()+250); days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); document.getElementById("timeDate").innerHTML = "运行"+dnum+"天"; } setInterval("createtime()",250); </script> <script defer src="https://bsz.211119.xyz/js"></script> </p> </footer> <script> // 国家数据 const countries = [ { name: "美国", code: "US" }, { name: "美国纽约", code: "NY US" }, { name: "美国洛杉矶", code: "California US" }, { name: "美国达拉斯", code: "Texas US" }, { name: "美国圣何塞", code: "CA US" }, { name: "美国芝加哥", code: "Illinois US" }, { name: "美国休斯敦", code: "TX US" }, { name: "美国菲尼克斯", code: "Arizona US" }, { name: "美国费城", code: "Pennsylvania US" }, { name: "美国圣安东尼奥", code: "Tx US" }, { name: "美国圣地亚哥", code: "Ca US" }, { name: "美国西雅图", code: "Washington US" }, { name: "德国", code: "DE" }, { name: "德国柏林", code: "Berlin DE" }, { name: "德国慕尼黑", code: "Bavaria DE" }, { name: "法国", code: "FR" }, { name: "法国巴黎", code: "Île-de-France FR" }, { name: "法国马赛", code: "Provence-Alpes-Côte d'Azur FR" }, { name: "越南", code: "VN" }, { name: "巴西", code: "BR" }, { name: "墨西哥", code: "MX" }, { name: "韩国", code: "Seoul KR" }, { name: "韩国首尔", code: "KR" }, { name: "意大利", code: "IT" }, { name: "西班牙", code: "ES" }, { name: "西班牙马德里", code: "Comunidad de Madrid ES" }, { name: "西班牙马德里巴塞罗那", code: "Cataluña ES" }, { name: "土耳其", code: "TR" }, { name: "埃及", code: "EG" }, { name: "印度尼西亚", code: "ID" }, // 以下邮编末知 { name: "英国", code: "UK" }, { name: "英国伦敦", code: "London UK" }, { name: "中国", code: "CN" }, { name: "中国台湾", code: "TW" }, { name: "中国香港", code: "HK" }, { name: "日本", code: "JP" }, { name: "日本东京", code: "Tokyo JP" }, { name: "日本大坂", code: "Osaka JP" }, { name: "印度", code: "IN" }, { name: "澳大利亚", code: "AU" }, { name: "加拿大", code: "CA" }, { name: "加拿大多伦多", code: "Ontario CA" }, { name: "俄罗斯", code: "RU" }, { name: "南非", code: "ZA" }, { name: "沙特阿拉伯", code: "SA" }, { name: "阿根廷", code: "AR" }, { name: "尼日利亚", code: "NG" } ]; // 初始化国家选择下拉框 function initCountrySelect() { const select = document.getElementById('country'); countries.forEach(country => { const option = document.createElement('option'); option.value = country.code; option.textContent = country.name; select.appendChild(option); }); // 添加返回主页按钮的点击事件 document.querySelector('a[href="/about"]').addEventListener('click', function(e) { e.preventDefault(); showAbout(); }); // 添加返回主页按钮的点击事件(在页脚也添加了一个) document.querySelector('a[href="/"]').addEventListener('click', function(e) { e.preventDefault(); showHome(); }); } // 复制到剪贴板 function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { const copied = document.getElementById('copied'); copied.classList.remove('hidden'); copied.classList.add('translate-y-0'); copied.classList.remove('translate-y-[-100%]'); setTimeout(() => { copied.classList.add('translate-y-[-100%]'); copied.classList.remove('translate-y-0'); setTimeout(() => { copied.classList.add('hidden'); }, 300); }, 2000); }); } // 显示/隐藏加载动画 function toggleLoading(show) { const loading = document.getElementById('loading'); if (show) { loading.classList.remove('hidden'); } else { loading.classList.add('hidden'); } } // 更改国家 function changeCountry(country) { toggleLoading(true); generateNewAddress(country); } // 保存地址 function saveAddress() { const note = prompt('请输入备注(可以留空)') || ''; const savedAddresses = JSON.parse(localStorage.getItem('savedAddresses') || '[]'); const newEntry = { note: note, name: document.getElementById('name').textContent, gender: document.getElementById('gender').textContent, phone: document.getElementById('phone').textContent, address: document.getElementById('address').textContent }; savedAddresses.push(newEntry); localStorage.setItem('savedAddresses', JSON.stringify(savedAddresses)); renderSavedAddresses(); } // 渲染保存的地址 function renderSavedAddresses() { const savedAddresses = JSON.parse(localStorage.getItem('savedAddresses') || '[]'); const tbody = document.querySelector('#savedAddressesTable tbody'); tbody.innerHTML = ''; savedAddresses.forEach((entry, index) => { const row = tbody.insertRow(); row.className = 'border-t border-gray-200 hover:bg-gray-50 transition-colors'; const cells = ['name', 'gender', 'phone', 'address', 'note', '']; cells.forEach((cell, i) => { const td = row.insertCell(); td.className = 'p-4'; if (i === cells.length - 1) { const deleteBtn = document.createElement('button'); deleteBtn.textContent = '删除'; deleteBtn.className = 'bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition-all transform hover:scale-105 focus:ring-2 focus:ring-red-500 focus:ring-opacity-50'; deleteBtn.onclick = () => { if (confirm('确定要删除这条记录吗?')) { savedAddresses.splice(index, 1); localStorage.setItem('savedAddresses', JSON.stringify(savedAddresses)); renderSavedAddresses(); } }; td.appendChild(deleteBtn); } else { td.textContent = entry[cell]; } }); }); } // 生成新地址 async function generateNewAddress(country) { if (!country) { country = document.getElementById('country').value; } toggleLoading(true); try { const response = await fetch(\`\${window.location.href}api?country=\${country}\`); const data = await response.json(); if (data.error) { alert(data.error); return; } // 提取邮编逻辑 const addressText = data.address || ''; const postcodeMatch = addressText.match(/\\b\\d{5}(?:\\-\\d{4})?\\b/g); // 匹配国际通用的邮编格式 const postcode = postcodeMatch ? postcodeMatch[0] : '未知『地址中倒数第2项提取』'; document.getElementById('name').textContent = data.name; document.getElementById('gender').textContent = data.gender; document.getElementById('phone').textContent = data.phone; document.getElementById('address').textContent = addressText; // 显示完整地址 document.getElementById('postcode').textContent = postcode; // 显示邮编 // 更新地图 document.getElementById('map').src = \`https://www.google.com/maps?q=\${encodeURIComponent(data.address)}&output=embed\`; } catch (error) { console.error('Error fetching address:', error); showErrorModal('获取地址时发生错误,请检查网络后点击重试', () => { generateNewAddress(document.getElementById('country').value); }); } finally { toggleLoading(false); } } // 页面加载时初始化 window.onload = function() { initCountrySelect(); generateNewAddress(); renderSavedAddresses(); }; // 显示关于页面 function showAbout() { document.getElementById('main-content').classList.add('hidden'); document.getElementById('about').classList.remove('hidden'); } // 返回主页 function showHome() { document.getElementById('about').classList.add('hidden'); document.getElementById('main-content').classList.remove('hidden'); } </script> </body> </html>`; async function handleRequest(request) { const url = new URL(request.url); const path = url.pathname; // 处理 API 请求 if (path === '/api') { // 原有的 API 处理逻辑 return handleApiRequest(request); } // 处理根路径请求,返回 HTML 页面 return new Response(htmlContent, { headers: { 'Content-Type': 'text/html;charset=UTF-8', ...corsHeaders } }); } // 将原有的处理逻辑移到单独的函数中 async function handleApiRequest(request) { if (request.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } if (request.method !== 'GET') { return new Response('Method not allowed', { status: 405 }); } const url = new URL(request.url); const country = url.searchParams.get('country') || 'US'; if (!countryCoordinates[country]) { return new Response(JSON.stringify({ error: 'Invalid country code' }), { status: 400, headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } let attempts = 0; const maxAttempts = 20; while (attempts < maxAttempts) { try { const location = getRandomLocation(country); const apiUrl = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${location.lat}&lon=${location.lng}&zoom=18&addressdetails=1`; const response = await fetch(apiUrl, { headers: { 'User-Agent': 'Cloudflare Worker Random Address Generator' } }); const data = await response.json(); if (isValidAddress(data)) { let city = data.address.city || data.address.town || ''; city = city.split(';')[0].trim(); const address = `${data.address.house_number} ${data.address.road}, ${city}, ${data.address.postcode || ''}, ${country}`.replace(/\s+/g, ' ').trim(); const name = getRandomName(country); const gender = Math.random() > 0.4 ? 'Male男' : 'Female女'; const phone = getRandomPhoneNumber(country); const result = { name, gender, phone, address, coordinates: { lat: location.lat, lng: location.lng } }; return new Response(JSON.stringify(result), { headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } attempts++; if (attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 100)); } } catch (error) { attempts++; if (attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 100)); } } } return new Response(JSON.stringify({ error: 'Failed to generate valid address after multiple attempts' }), { status: 500, headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } // 注册事件监听器 addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); 2025年07月15日更新,界面调整,添加多个国家和地区// 国家坐标数据 const countryCoordinates = { "US": [{ lat: 37.7749, lng: -122.4194 }, { lat: 34.0522, lng: -118.2437 }, { lat: 32.7767, lng: -96.7970 }, { lat: 41.8781, lng: -87.6298 }], "NY US": [{ lat: 40.7128, lng: -74.0060 }], "California US": [{ lat: 34.0522, lng: -118.2437 }], "Texas US": [{ lat: 32.7767, lng: -96.7970 }], "CA US": [{ lat: 37.3382, lng: -121.8863 }], "Illinois US": [{ lat: 41.8781, lng: -87.6298 }], "UK": [{ lat: 51.5074, lng: -0.1278 }, { lat: 53.4808, lng: -2.2426 }], "FR": [{ lat: 48.8566, lng: 2.3522 }, { lat: 45.7640, lng: 4.8357 }], "DE": [{ lat: 52.5200, lng: 13.4050 }, { lat: 48.1351, lng: 11.5820 }], "CN": [{ lat: 39.9042, lng: 116.4074 }, { lat: 31.2304, lng: 121.4737 }], "TW": [{ lat: 25.0330, lng: 121.5654 }, { lat: 22.6273, lng: 120.3014 }], "HK": [{ lat: 22.3193, lng: 114.1694 },{ lat: 22.3964, lng: 114.1095 }], "JP": [{ lat: 35.6895, lng: 139.6917 }, { lat: 34.6937, lng: 135.5023 }], "IN": [{ lat: 28.6139, lng: 77.2090 }, { lat: 19.0760, lng: 72.8777 }], "AU": [{ lat: -33.8688, lng: 151.2093 }, { lat: -37.8136, lng: 144.9631 }], "BR": [{ lat: -23.5505, lng: -46.6333 }, { lat: -22.9068, lng: -43.1729 }], "CA": [{ lat: 43.651070, lng: -79.347015 }, { lat: 45.501690, lng: -73.567253 }], "RU": [{ lat: 55.7558, lng: 37.6173 }, { lat: 59.9343, lng: 30.3351 }], "ZA": [{ lat: -33.9249, lng: 18.4241 }, { lat: -26.2041, lng: 28.0473 }], "MX": [{ lat: 19.4326, lng: -99.1332 }, { lat: 20.6597, lng: -103.3496 }], "KR": [{ lat: 37.5665, lng: 126.9780 }, { lat: 35.1796, lng: 129.0756 }], "IT": [{ lat: 41.9028, lng: 12.4964 }, { lat: 45.4642, lng: 9.1900 }], "ES": [{ lat: 40.4168, lng: -3.7038 }, { lat: 41.3851, lng: 2.1734 }], "TR": [{ lat: 41.0082, lng: 28.9784 }, { lat: 39.9334, lng: 32.8597 }], "SA": [{ lat: 24.7136, lng: 46.6753 }, { lat: 21.3891, lng: 39.8579 }], "AR": [{ lat: -34.6037, lng: -58.3816 }, { lat: -31.4201, lng: -64.1888 }], "EG": [{ lat: 30.0444, lng: 31.2357 }, { lat: 31.2156, lng: 29.9553 }], "NG": [{ lat: 6.5244, lng: 3.3792 }, { lat: 9.0579, lng: 7.4951 }], "ID": [{ lat: -6.2088, lng: 106.8456 }, { lat: -7.7956, lng: 110.3695 }], "VN": [{ lat: 21.0285, lng: 105.8048 }, { lat: 10.7626, lng: 106.6602 }], // 添加越南坐标数据 }; // 姓名数据 const namesByCountry = { "CN": { first: ["李", "王", "张", "刘", "陈", "杨", "黄", "赵", "吴", "周", "孙", "苏", "马", "朱", "候", "郭", "黑", "高", "林", "钱", "冯", "卫", "蒋", "许", "吕", "施", "曹", "严", "魏", "陶", "方", "雷"], last: ["力", "斌", "那", "真", "杰", "京", "丽", "晴", "来", "东", "勇", "仕", "云", "洁", "山", "伟", "明", "亮", "刚", "飞", "英", "兴", "浩", "曙光", "平", "志远", "志珍", "第一", "建国", "玉仙", "现红", "瑞山", "一山", "新丽", "思思", "青凤", "秀美"] }, "JP": { first: ["Sato", "Suzuki", "Takahashi", "Tanaka", "Watanabe", "Ito", "Yamamoto", "Nakamura", "Kobayashi", "Kato"], last: ["Shota", "Ren", "Hina", "Yui", "Hiroto", "Sota", "Yota", "Misaki", "Nanami", "Yuto"] }, "KR": { first: ["Kim", "Lee", "Park", "Choi", "Jung", "Kang", "Jo", "Yoon", "Jang", "Lim"], last: ["Minjun", "Seojun", "Doyun", "Jiho", "Jihun", "Seoyeon", "Seoyun", "Jiwoo", "Seohyun", "Minseo"] }, "TW": { first: ["Chen", "Lin", "Huang", "Chang", "Lee", "Wang", "Wu", "Liu", "Tsai", "Yang"], last: ["Zhiming", "Jianhong", "Junjie", "Yijun", "Shufen", "Meiling", "Yating", "Jiahao", "Zhihao", "Shuhui"] }, "HK": { first: ["Chan", "Lee", "Wong", "Cheung", "Lau", "Wang", "Ng", "Cheng", "Leung", "Ho"], last: ["Chiming", "Kayan", "Junjie", "Wingsze", "Kaming", "Meiling", "Kahao", "Winger", "Chihao", "Shukfan"] }, "US": { first: ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"], last: ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Christopher"] }, "NY US": { first: ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"], last: ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Christopher"] }, "California US": { first: ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"], last: ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Christopher"] }, "Texas US": { first: ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"], last: ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Christopher"] }, "CA US": { first: ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"], last: ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Christopher"] }, "Illinois US": { first: ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"], last: ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Christopher"] }, "UK": { first: ["Smith", "Jones", "Williams", "Taylor", "Brown", "Davies", "Evans", "Wilson", "Thomas", "Roberts"], last: ["Oliver", "Jack", "Harry", "George", "Noah", "Charlie", "Jacob", "Oscar", "William", "Leo"] }, "FR": { first: ["Martin", "Bernard", "Dubois", "Thomas", "Robert", "Richard", "Petit", "Durand", "Leroy", "Moreau"], last: ["Lucas", "Louis", "Gabriel", "Arthur", "Jules", "Hugo", "Leo", "Adam", "Raphael", "Paul"] }, "DE": { first: ["Mueller", "Schmidt", "Schneider", "Fischer", "Weber", "Meyer", "Wagner", "Becker", "Schulz", "Hoffmann"], last: ["Ben", "Paul", "Leon", "Noah", "Luis", "Finn", "Felix", "Jonas", "Maximilian", "Henry"] }, "IT": { first: ["Rossi", "Ferrari", "Russo", "Bianchi", "Romano", "Gallo", "Costa", "Fontana", "Conti", "Esposito"], last: ["Leonardo", "Francesco", "Alessandro", "Lorenzo", "Matteo", "Andrea", "Gabriele", "Marco", "Antonio", "Giuseppe"] }, "ES": { first: ["Garcia", "Rodriguez", "Gonzalez", "Fernandez", "Lopez", "Martinez", "Sanchez", "Perez", "Martin", "Gomez"], last: ["Antonio", "Jose", "Manuel", "Francisco", "David", "Juan", "Miguel", "Javier", "Rafael", "Carlos"] }, "BR": { first: ["Silva", "Santos", "Oliveira", "Souza", "Rodrigues", "Ferreira", "Alves", "Pereira", "Lima", "Gomes"], last: ["Miguel", "Arthur", "Heitor", "Pedro", "Davi", "Gabriel", "Bernardo", "Lucas", "Matheus", "Rafael"] }, "RU": { first: ["Ivanov", "Smirnov", "Kuznetsov", "Popov", "Vasiliev", "Petrov", "Sokolov", "Mikhailov", "Fedorov", "Morozov"], last: ["Alexander", "Dmitry", "Maxim", "Ivan", "Andrey", "Mikhail", "Artem", "Daniel", "Roman", "Sergey"] }, "IN": { first: ["Kumar", "Singh", "Sharma", "Patel", "Gupta", "Shah", "Verma", "Rao", "Reddy", "Joshi"], last: ["Aarav", "Vihaan", "Vivaan", "Aditya", "Arjun", "Reyansh", "Ayaan", "Sai", "Krishna", "Ishaan"] }, "AU": { first: ["Smith", "Jones", "Williams", "Brown", "Wilson", "Taylor", "Johnson", "White", "Anderson", "Thompson"], last: ["Oliver", "William", "Jack", "Noah", "Thomas", "James", "Lucas", "Henry", "Ethan", "Alexander"] }, "CA": { first: ["Smith", "Brown", "Tremblay", "Martin", "Roy", "Wilson", "MacDonald", "Taylor", "Campbell", "Anderson"], last: ["Liam", "Noah", "Oliver", "William", "James", "Benjamin", "Lucas", "Henry", "Theodore", "Jack"] }, "MX": { first: ["Garcia", "Rodriguez", "Martinez", "Lopez", "Gonzalez", "Perez", "Sanchez", "Ramirez", "Torres", "Flores"], last: ["Santiago", "Mateo", "Sebastian", "Leonardo", "Diego", "Daniel", "Gabriel", "Adrian", "David", "Alexander"] }, "TR": { first: ["Yilmaz", "Kaya", "Demir", "Sahin", "Celik", "Yildiz", "Erdogan", "Ozturk", "Aydin", "Ozdemir"], last: ["Yusuf", "Eymen", "Ömer", "Mustafa", "Ali", "Mehmet", "Ahmet", "Emir", "Hamza", "Ibrahim"] }, "SA": { first: ["Al-Saud", "Al-Sheikh", "Al-Rashid", "Al-Qahtani", "Al-Ghamdi", "Al-Zahrani", "Al-Dossari", "Al-Shammari", "Al-Otaibi", "Al-Harbi"], last: ["Mohammed", "Abdullah", "Ahmed", "Ali", "Omar", "Ibrahim", "Khalid", "Hassan", "Fahad", "Abdul"] }, "AR": { first: ["Gonzalez", "Rodriguez", "Garcia", "Fernandez", "Lopez", "Martinez", "Perez", "Romero", "Sanchez", "Diaz"], last: ["Mateo", "Thiago", "Benjamin", "Valentino", "Santiago", "Juan", "Lucas", "Martin", "Nicolas", "Joaquin"] }, "EG": { first: ["Mohamed", "Ahmed", "Mahmoud", "Ibrahim", "Ali", "Hassan", "Hussein", "Mostafa", "Kamal", "Samir"], last: ["Omar", "Youssef", "Adam", "Malik", "Zain", "Hamza", "Kareem", "Hassan", "Ali", "Ibrahim"] }, "NG": { first: ["Okafor", "Adebayo", "Okonkwo", "Eze", "Oluwaseun", "Adegoke", "Afolabi", "Ogunleye", "Adeniyi", "Adesina"], last: ["Oluwadamilare", "Oluwatobiloba", "Ayomide", "Temitope", "Oluwaseun", "Adebayo", "Chibuike", "Chisom", "Chidi", "Obinna"] }, "ID": { first: ["Wijaya", "Kusuma", "Suryanto", "Halim", "Santoso", "Tanaka", "Wibowo", "Susanto", "Hidayat", "Putra"], last: ["Muhammad", "Ahmad", "Abdul", "Aditya", "Budi", "Dimas", "Eko", "Fajar", "Gading", "Hadi"] }, "ZA": { first: ["Nkosi", "Van der Merwe", "Botha", "Mkhize", "Khumalo", "Pretorius", "Venter", "Ndlovu", "Fourie", "Nel"], last: ["Bandile", "Themba", "Sipho", "Thabo", "Jabu", "Mandla", "Blessing", "Gift", "Lucky", "Precious"] }, "VN": { first: ["Nguyen", "Tran", "Le", "Pham", "Hoang", "Vu", "Do", "Dao", "Bui", "Dang"], last: ["Van", "Minh", "Thanh", "Ngoc", "Huu", "Quoc", "Xuan", "Duc", "Tuan", "Khanh"] } }; // 电话号码格式配置 const phoneFormats = { "US": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[201, 989]] }, "NY US": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[201, 989]] }, "California US": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[201, 989]] }, "Texas US": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[201, 989]] }, "CA US": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[201, 989]] }, "Illinois US": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[201, 989]] }, "CN": { format: "+86 1XX-XXXX-XXXX", mobilePrefix: ["30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "50", "51", "52", "53", "55", "56", "57", "58", "59", "66", "70", "71", "72", "73", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89"] }, "JP": { format: "+81 XX-XXXX-XXXX", mobilePrefix: ["70", "80", "90"] }, "KR": { format: "+82 10-XXXX-XXXX" }, "UK": { format: "+44 7XXX XXXXXX", mobilePrefix: ["7"] }, "FR": { format: "+33 6 XX XX XX XX", mobilePrefix: ["6", "7"] }, "DE": { format: "+49 15X XXXXXXXX", mobilePrefix: ["15", "16", "17"] }, "TW": { format: "+886 9XX-XXX-XXX" }, "HK": { format: "+852 XXXX XXXX", mobilePrefix: ["5", "6", "9"] }, "AU": { format: "+61 4XX XXX XXX", mobilePrefix: ["4"] }, "CA": { format: "+1 (XXX) XXX-XXXX", areaCodeRanges: [[204, 989]] }, "MX": { format: "+52 1XX XXX XXXX" }, "TR": { format: "+90 5XX XXX XXXX", mobilePrefix: ["5"] }, "SA": { format: "+966 5XX XXX XXXX", mobilePrefix: ["5"] }, "AR": { format: "+54 9XX XXXX-XXXX" }, "EG": { format: "+20 1XX XXX XXXX", mobilePrefix: ["1"] }, "NG": { format: "+234 8XX XXX XXXX", mobilePrefix: ["7", "8", "9"] }, "ID": { format: "+62 8XX-XXXX-XXXX", mobilePrefix: ["8"] }, "ZA": { format: "+27 8X XXX XXXX", mobilePrefix: ["6", "7", "8"] }, "VN": { format: "+84 9X XXX XXXX", mobilePrefix: ["9", "8"] } }; // 工具函数 function getRandomLocation(country) { const coordsArray = countryCoordinates[country]; const randomCity = coordsArray[Math.floor(Math.random() * coordsArray.length)]; const lat = randomCity.lat + (Math.random() - 0.5) * 0.1; const lng = randomCity.lng + (Math.random() - 0.5) * 0.1; return { lat, lng }; } function getRandomName(country) { if (!namesByCountry[country]) { return null; } const names = namesByCountry[country]; const firstName = names.first[Math.floor(Math.random() * names.first.length)]; const lastName = names.last[Math.floor(Math.random() * names.last.length)]; return `${firstName} ${lastName}`; } function generateAreaCode(ranges) { const range = ranges[Math.floor(Math.random() * ranges.length)]; const [min, max] = range; return Math.floor(min + Math.random() * (max - min + 1)); } function getRandomPhoneNumber(country) { const format = phoneFormats[country] || phoneFormats["US"]; let phone = format.format; if (format.areaCodeRanges) { const areaCode = generateAreaCode(format.areaCodeRanges); phone = phone.replace("XXX", areaCode); phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } else if (format.mobilePrefix) { const prefix = format.mobilePrefix[Math.floor(Math.random() * format.mobilePrefix.length)]; // 先替换前缀 if (prefix.length === 2) { phone = phone.replace(/XX/, prefix); } else { phone = phone.replace(/X/, prefix); } // 然后替换剩余的X phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } else { phone = phone.replace(/X/g, () => Math.floor(Math.random() * 10)); } return phone; } function isValidAddress(data) { return data && data.address && data.address.house_number && data.address.road && (data.address.city || data.address.town); } // 处理CORS请求的headers const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, HEAD, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }; // HTML 模板 const htmlContent = `<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>随机地址生成器</title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet"> <script> tailwind.config = { theme: { extend: { animation: { 'gradient': 'gradient 8s linear infinite', }, keyframes: { gradient: { '0%, 100%': { 'background-size': '200% 200%', 'background-position': 'left center' }, '50%': { 'background-size': '200% 200%', 'background-position': 'right center' } } } } } } </script> </head> <link rel="shortcut icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2280%22>🌐</text></svg>"> <body class="bg-gradient-to-br from-blue-50 via-white to-blue-50 text-gray-800 min-h-screen font-['Noto_Sans_SC']"> <!-- 头部 --> <header class="bg-gradient-to-r from-blue-500 via-sky-500 to-blue-500 animate-gradient w-full p-6 shadow-lg"> <div class="max-w-4xl mx-auto flex items-center justify-between"> <div class="flex items-center gap-3"> <img src="https://img.freepik.com/premium-vector/minimal-location-map-icon-logo-symbol-vector-design-transparent_965979-613.jpg?w=2000" alt="Logo" class="w-12 h-12 transform hover:scale-105 transition-transform"> <h1 class="text-2xl font-bold text-white">随机地址生成器</h1> </div> <a href="https://www.199881.xyz" target="_blank" class="flex items-center gap-2 text-white hover:text-gray-200 transition-colors"> <svg viewBox="0 0 16 16" class="w-6 h-6 fill-current" aria-hidden="true"> <img src="https://cdn.glitch.global/efdace30-a873-49c7-aaa9-4fa31679ee0c/logo04.png?1741698119024" alt="GitHub" class="w-5 h-5 ml-1"> </svg> <span class="font-medium">导航</span> </a> </div> </header> <!-- 主要内容 --> <main class="container mx-auto px-4 py-8 max-w-5xl"> <!-- 加载动画 --> <div id="loading" class="hidden fixed inset-0 bg-white bg-opacity-75 backdrop-blur-sm flex items-center justify-center z-50"> <div class="bg-white rounded-2xl p-8 flex flex-col items-center shadow-2xl"> <div class="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-blue-500 mb-4"></div> <div class="text-gray-800 text-lg font-medium">正在加载...</div> </div> </div> <div id="copied" class="hidden fixed top-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg z-40 transform transition-transform duration-300"> 已复制到剪贴板! </div> <!-- 国家选择 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200 mb-8"> <div class="flex flex-col sm:flex-row items-start sm:items-center gap-4"> <div class="w-full sm:w-auto flex flex-col sm:flex-row items-start sm:items-center gap-2 flex-grow"> <label for="country" class="text-blue-600 font-bold whitespace-nowrap">选择国家/地区:</label> <select id="country" onchange="changeCountry(this.value)" class="w-full bg-gray-50 border border-gray-200 rounded-xl p-3 text-gray-800 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"> </select> </div> <button onclick="generateNewAddress(document.getElementById('country').value)" class="w-full sm:w-auto bg-gradient-to-r from-blue-500 to-sky-500 hover:from-blue-600 hover:to-sky-600 text-white font-bold py-3 px-6 rounded-xl transition-all transform hover:scale-105 hover:shadow-lg focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50"> 获取新地址 </button> </div> </div> <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <!-- 左侧面板 --> <div class="space-y-6"> <!-- 信息卡片 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">个人信息</h2> <div class="space-y-4"> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">姓名:</strong><span id="name" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">性别:</strong><span id="gender" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">电话:</strong><span id="phone" class="ml-2"></span> </div> <div class="bg-gray-50 p-4 rounded-xl cursor-pointer hover:bg-gray-100 transition-all transform hover:scale-[1.02] hover:shadow-lg" onclick="copyToClipboard(this.querySelector('span').textContent)"> <strong class="text-blue-600">地址:</strong><span id="address" class="ml-2"></span> </div> </div> </div> <!-- 保存按钮 --> <button onclick="saveAddress()" class="w-full bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white font-bold py-3 px-6 rounded-xl transition-all transform hover:scale-105 hover:shadow-lg focus:ring-2 focus:ring-green-500 focus:ring-opacity-50"> 保存地址 </button> </div> <!-- 右侧面板 --> <div class="space-y-6"> <!-- 地图 --> <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">地图预览</h2> <iframe id="map" class="w-full h-[360px] rounded-xl border border-gray-200"></iframe> </div> </div> </div> <!-- 已保存的地址表格 --> <div class="mt-8 bg-white rounded-2xl shadow-xl p-6 border border-gray-200"> <h2 class="text-xl font-bold mb-6 text-blue-600">已保存的地址</h2> <div class="overflow-x-auto"> <table class="w-full border-collapse" id="savedAddressesTable"> <thead> <tr class="bg-gradient-to-r from-blue-500 to-sky-500 text-white"> <th class="p-4 text-left rounded-tl-lg">姓名</th> <th class="p-4 text-left">性别</th> <th class="p-4 text-left">电话</th> <th class="p-4 text-left">地址</th> <th class="p-4 text-left">备注</th> <th class="p-4 text-left rounded-tr-lg">操作</th> </tr> </thead> <tbody></tbody> </table> </div> </div> </main> <!-- 页脚 --> <footer class="text-center py-8 text-gray-600 text-sm mt-8 bg-gray-50 border-t border-gray-200"> <p class="max-w-4xl mx-auto px-4"> 总访问量 <span id="busuanzi_site_pv"></span> 次 | <span id="timeDate">载入天数...</span> | <a href="https://boke.199881.xyz/" target="_blank"> <span style="color: blue;">博客 | <a href="https://www.199881.xyz/" target="_blank"> <span style="color: green;">导航 <a href="https://github.com/jiangnan1224/AddressGenerator/" target="_blank" class="inline-flex items-center hover:text-blue-600 transition-colors"> <img src="https://pic.imgdb.cn/item/66e7ab36d9c307b7e9cefd24.png" alt="GitHub" class="w-5 h-5 ml-1"> </a> <script language="javascript"> var now = new Date(); function createtime(){ var grt= new Date("04/23/2025 00:00:00");/*---这里是网站的启用时间--*/ now.setTime(now.getTime()+250); days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); document.getElementById("timeDate").innerHTML = "运行"+dnum+"天"; } setInterval("createtime()",250); </script> <script defer src="https://bsz.211119.xyz/js"></script> </p> </footer> <script> // 国家数据 const countries = [ { name: "美国", code: "US" }, { name: "美国纽约", code: "NY US" }, { name: "美国洛杉矶", code: "California US" }, { name: "美国达拉斯", code: "Texas US" }, { name: "美国圣何塞", code: "CA US" }, { name: "美国芝加哥", code: "Illinois US" }, { name: "英国", code: "UK" }, { name: "法国", code: "FR" }, { name: "德国", code: "DE" }, { name: "中国", code: "CN" }, { name: "中国台湾", code: "TW" }, { name: "中国香港", code: "HK" }, { name: "日本", code: "JP" }, { name: "越南", code: "VN" }, { name: "印度", code: "IN" }, { name: "澳大利亚", code: "AU" }, { name: "巴西", code: "BR" }, { name: "加拿大", code: "CA" }, { name: "俄罗斯", code: "RU" }, { name: "南非", code: "ZA" }, { name: "墨西哥", code: "MX" }, { name: "韩国", code: "KR" }, { name: "意大利", code: "IT" }, { name: "西班牙", code: "ES" }, { name: "土耳其", code: "TR" }, { name: "沙特阿拉伯", code: "SA" }, { name: "阿根廷", code: "AR" }, { name: "埃及", code: "EG" }, { name: "尼日利亚", code: "NG" }, { name: "印度尼西亚", code: "ID" } ]; // 初始化国家选择下拉框 function initCountrySelect() { const select = document.getElementById('country'); countries.forEach(country => { const option = document.createElement('option'); option.value = country.code; option.textContent = country.name; select.appendChild(option); }); } // 复制到剪贴板 function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { const copied = document.getElementById('copied'); copied.classList.remove('hidden'); copied.classList.add('translate-y-0'); copied.classList.remove('translate-y-[-100%]'); setTimeout(() => { copied.classList.add('translate-y-[-100%]'); copied.classList.remove('translate-y-0'); setTimeout(() => { copied.classList.add('hidden'); }, 300); }, 2000); }); } // 显示/隐藏加载动画 function toggleLoading(show) { const loading = document.getElementById('loading'); if (show) { loading.classList.remove('hidden'); } else { loading.classList.add('hidden'); } } // 更改国家 function changeCountry(country) { toggleLoading(true); generateNewAddress(country); } // 保存地址 function saveAddress() { const note = prompt('请输入备注(可以留空)') || ''; const savedAddresses = JSON.parse(localStorage.getItem('savedAddresses') || '[]'); const newEntry = { note: note, name: document.getElementById('name').textContent, gender: document.getElementById('gender').textContent, phone: document.getElementById('phone').textContent, address: document.getElementById('address').textContent }; savedAddresses.push(newEntry); localStorage.setItem('savedAddresses', JSON.stringify(savedAddresses)); renderSavedAddresses(); } // 渲染保存的地址 function renderSavedAddresses() { const savedAddresses = JSON.parse(localStorage.getItem('savedAddresses') || '[]'); const tbody = document.querySelector('#savedAddressesTable tbody'); tbody.innerHTML = ''; savedAddresses.forEach((entry, index) => { const row = tbody.insertRow(); row.className = 'border-t border-gray-200 hover:bg-gray-50 transition-colors'; const cells = ['name', 'gender', 'phone', 'address', 'note', '']; cells.forEach((cell, i) => { const td = row.insertCell(); td.className = 'p-4'; if (i === cells.length - 1) { const deleteBtn = document.createElement('button'); deleteBtn.textContent = '删除'; deleteBtn.className = 'bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition-all transform hover:scale-105 focus:ring-2 focus:ring-red-500 focus:ring-opacity-50'; deleteBtn.onclick = () => { if (confirm('确定要删除这条记录吗?')) { savedAddresses.splice(index, 1); localStorage.setItem('savedAddresses', JSON.stringify(savedAddresses)); renderSavedAddresses(); } }; td.appendChild(deleteBtn); } else { td.textContent = entry[cell]; } }); }); } // 生成新地址 async function generateNewAddress(country) { if (!country) { country = document.getElementById('country').value; } toggleLoading(true); try { const response = await fetch(\`\${window.location.href}api?country=\${country}\`); const data = await response.json(); if (data.error) { alert(data.error); return; } document.getElementById('name').textContent = data.name; document.getElementById('gender').textContent = data.gender; document.getElementById('phone').textContent = data.phone; document.getElementById('address').textContent = data.address; // 更新地图 document.getElementById('map').src = \`https://www.google.com/maps?q=\${encodeURIComponent(data.address)}&output=embed\`; } catch (error) { console.error('Error fetching address:', error); alert('获取地址时发生错误,请重试'); } finally { toggleLoading(false); } } // 页面加载时初始化 window.onload = function() { initCountrySelect(); generateNewAddress(); renderSavedAddresses(); }; </script> </body> </html>`; async function handleRequest(request) { const url = new URL(request.url); const path = url.pathname; // 处理 API 请求 if (path === '/api') { // 原有的 API 处理逻辑 return handleApiRequest(request); } // 处理根路径请求,返回 HTML 页面 return new Response(htmlContent, { headers: { 'Content-Type': 'text/html;charset=UTF-8', ...corsHeaders } }); } // 将原有的处理逻辑移到单独的函数中 async function handleApiRequest(request) { if (request.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } if (request.method !== 'GET') { return new Response('Method not allowed', { status: 405 }); } const url = new URL(request.url); const country = url.searchParams.get('country') || 'US'; if (!countryCoordinates[country]) { return new Response(JSON.stringify({ error: 'Invalid country code' }), { status: 400, headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } let attempts = 0; const maxAttempts = 20; while (attempts < maxAttempts) { try { const location = getRandomLocation(country); const apiUrl = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${location.lat}&lon=${location.lng}&zoom=18&addressdetails=1`; const response = await fetch(apiUrl, { headers: { 'User-Agent': 'Cloudflare Worker Random Address Generator' } }); const data = await response.json(); if (isValidAddress(data)) { let city = data.address.city || data.address.town || ''; city = city.split(';')[0].trim(); const address = `${data.address.house_number} ${data.address.road}, ${city}, ${data.address.postcode || ''}, ${country}`.replace(/\s+/g, ' ').trim(); const name = getRandomName(country); const gender = Math.random() > 0.4 ? 'Male男' : 'Female女'; const phone = getRandomPhoneNumber(country); const result = { name, gender, phone, address, coordinates: { lat: location.lat, lng: location.lng } }; return new Response(JSON.stringify(result), { headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } attempts++; if (attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 100)); } } catch (error) { attempts++; if (attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 100)); } } } return new Response(JSON.stringify({ error: 'Failed to generate valid address after multiple attempts' }), { status: 500, headers: { 'Content-Type': 'application/json', ...corsHeaders } }); } // 注册事件监听器 addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); });
2025年07月15日
2 阅读
0 评论
0 点赞
您是第
165292
位访客