您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Busca Places sin nombre y les asigna la categoría como nombre en español.
当前为
// ==UserScript== // @name WME Auto Name Places // @namespace https://gf.qytechs.cn/es-419/users/67894-crotalo // @version 2.57 // @description Busca Places sin nombre y les asigna la categoría como nombre en español. // @author Crotalo // @match https://www.waze.com/*editor* // @match https://beta.waze.com/*editor* // @exclude https://beta.waze.com/*user/*editor/* // @exclude https://www.waze.com/*user/*editor/* // @exclude https://www.waze.com/discuss/* // @grant none // ==/UserScript== (function() { 'use strict'; // Configuración const CONFIG = { delayBetweenUpdates: 100, // ms entre actualizaciones modalStyle: { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', background: 'white', padding: '20px', border: '2px solid #ccc', borderRadius: '5px', boxShadow: '0 0 10px rgba(0,0,0,0.2)', zIndex: '10000', maxHeight: '70vh', overflowY: 'auto', width: 'auto', minWidth: '500px' } }; // Diccionario de traducción de categorías a español const CATEGORY_TRANSLATIONS = { 'restaurant': 'Restaurante', 'swimming_pool': 'Piscina', 'sea_lake_pool': 'Lago', 'river_stream': 'Río', 'forest_grove': 'Bosque', 'cafe': 'Cafetería', 'sports_court': 'Cancha Deportiva', 'shopping_and_services': 'Tienda', 'car_services': 'Servios para el Automovil', 'hotel': 'Hotel', 'sport_court': 'Escenario Deportivo', 'gas station': 'Estación de servicio', 'hospital': 'Hospital', 'pharmacy': 'Farmacia', 'bank': 'Banco', 'atm': 'Cajero automático', 'parking': 'Estacionamiento', 'parking_lot': 'Parqueadero', 'garage_automotive_shop': 'Tienda para Vehículos', 'natural_features': 'Características Naturales', 'school': 'Escuela', 'university': 'Universidad', 'museum': 'Museo', 'park': 'Parque', 'mall': 'Centro comercial', 'stadium_arena': 'Estadio', 'supermarket': 'Supermercado', 'gym': 'Gimnasio', 'church': 'Iglesia', 'police': 'Comisaría', 'fire station': 'Estación de bomberos', 'library': 'Biblioteca', 'stadium': 'Estadio', 'cinema': 'Cine', 'theater': 'Teatro', 'zoo': 'Zoológico', 'airport': 'Aeropuerto', 'train station': 'Estación de tren', 'bus station': 'Estación de autobuses', 'car wash': 'Lavado de coches', 'car repair': 'Taller mecánico', 'construction_site': 'Sitio en Construcción', 'dentist': 'Dentista', 'doctor': 'Médico', 'clinic': 'Clínica', 'veterinary': 'Veterinario', 'post office': 'Oficina de correos', 'shopping': 'Tiendas', 'bakery': 'Panadería', 'butcher': 'Carnicería', 'market': 'Mercado', 'florist': 'Florería', 'book store': 'Librería', 'electronics': 'Electrónica', 'furniture': 'Mueblería', 'jewelry': 'Joyería', 'optician': 'Óptica', 'pet store': 'Tienda de mascotas', 'sports': 'Artículos deportivos', 'toy store': 'Juguetería', 'department store': 'Grandes almacenes' }; // Función para esperar a que WME esté listo function waitForWME() { return new Promise(resolve => { if (window.W && W.model && W.model.venues && W.model.actionManager) { resolve(); } else { setTimeout(() => resolve(waitForWME()), 500); } }); } // Obtener places sin nombre (optimizado) function getUnnamedPlaces() { if (!W.model.venues?.objects) return []; return Object.values(W.model.venues.objects).filter(place => { const name = place.attributes?.name; return !name || name.trim() === ''; }); } // Generar nombre automático en español function generateName(place) { if (!place.attributes) return "Desconocido"; if (place.attributes.residential) return "Residencial"; if (place.attributes.categories?.[0]) { const category = place.attributes.categories[0].toLowerCase(); return CATEGORY_TRANSLATIONS[category] || category.charAt(0).toUpperCase() + category.slice(1); } return "Desconocido"; } // Crear tabla de aprobación (optimizado) function createApprovalTable(places) { // Eliminar modal existente document.getElementById('wme-auto-name-modal')?.remove(); const modal = document.createElement('div'); modal.id = 'wme-auto-name-modal'; Object.assign(modal.style, CONFIG.modalStyle); // Botón de cierre const closeBtn = document.createElement('button'); closeBtn.innerHTML = '×'; closeBtn.style.position = 'absolute'; closeBtn.style.right = '10px'; closeBtn.style.top = '10px'; closeBtn.style.background = 'transparent'; closeBtn.style.border = 'none'; closeBtn.style.fontSize = '20px'; closeBtn.style.cursor = 'pointer'; closeBtn.onclick = () => modal.remove(); modal.appendChild(closeBtn); // Título const title = document.createElement('h3'); title.textContent = `Places sin nombre encontrados: ${places.length}`; title.style.marginTop = '0'; title.style.color = '#333'; modal.appendChild(title); // Tabla const table = document.createElement('table'); table.style.width = '100%'; table.style.borderCollapse = 'collapse'; table.style.marginBottom = '15px'; const thead = document.createElement('thead'); thead.innerHTML = ` <tr style="background-color: #f5f5f5;"> <th style="padding: 8px; text-align: left; border-bottom: 1px solid #ddd;">ID</th> <th style="padding: 8px; text-align: left; border-bottom: 1px solid #ddd;">Categoría</th> <th style="padding: 8px; text-align: left; border-bottom: 1px solid #ddd;">Nuevo Nombre</th> <th style="padding: 8px; text-align: left; border-bottom: 1px solid #ddd;">Aprobar</th> </tr> `; table.appendChild(thead); const tbody = document.createElement('tbody'); places.forEach(place => { const row = document.createElement('tr'); row.style.borderBottom = '1px solid #eee'; const newName = generateName(place); const category = place.attributes.categories?.[0] ? (CATEGORY_TRANSLATIONS[place.attributes.categories[0].toLowerCase()] || place.attributes.categories[0]) : "N/A"; row.innerHTML = ` <td style="padding: 8px;">${place.attributes.id}</td> <td style="padding: 8px;">${category}</td> <td style="padding: 8px;">${newName}</td> <td style="padding: 8px; text-align: center;"> <input type='checkbox' data-id='${place.attributes.id}' checked> </td> `; tbody.appendChild(row); }); table.appendChild(tbody); modal.appendChild(table); // Botones const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.justifyContent = 'flex-end'; buttonContainer.style.gap = '10px'; const createButton = (text, color, onClick) => { const btn = document.createElement('button'); btn.textContent = text; btn.style.padding = '8px 16px'; btn.style.background = color; btn.style.color = 'white'; btn.style.border = 'none'; btn.style.borderRadius = '4px'; btn.style.cursor = 'pointer'; btn.onclick = onClick; return btn; }; buttonContainer.appendChild( createButton('Cancelar', '#f44336', () => modal.remove()) ); buttonContainer.appendChild( createButton('Aplicar Cambios', '#4CAF50', () => applyChanges(places)) ); modal.appendChild(buttonContainer); document.body.appendChild(modal); } // Aplicar cambios seleccionados async function applyChanges(places) { const modal = document.getElementById('wme-auto-name-modal'); if (!modal) return; const applyBtn = modal.querySelector('button:last-child'); const checkboxes = modal.querySelectorAll("input[type='checkbox']:checked"); const UpdateObject = require("Waze/Action/UpdateObject"); if (!checkboxes.length) { alert('No hay cambios seleccionados para aplicar.'); return; } try { // Deshabilitar botón durante la operación applyBtn.disabled = true; applyBtn.textContent = 'Guardando...'; applyBtn.style.background = '#cccccc'; let changesMade = false; let successCount = 0; // Procesar cada checkbox seleccionado for (const checkbox of checkboxes) { const placeId = checkbox.dataset.id; const place = W.model.venues.getObjectById(placeId); if (!place) { console.warn(`⛔ No se encontró el lugar con ID: ${placeId}`); continue; } const newName = generateName(place); const currentName = place.attributes.name || ""; if (newName && newName !== "" && currentName.trim() !== newName) { try { const action = new UpdateObject(place, { name: newName }); W.model.actionManager.add(action); console.log(`✅ Nombre actualizado: "${currentName}" → "${newName}"`); changesMade = true; successCount++; // Pequeña pausa entre cambios await new Promise(resolve => setTimeout(resolve, CONFIG.delayBetweenUpdates)); } catch (error) { console.error(`⛔ Error actualizando place ${placeId}:`, error); } } else { console.log(`⏭ Sin cambios reales para ID ${placeId} (ya tiene nombre o no es necesario cambiarlo)`); } } modal.remove(); if (changesMade) { alert(`💾 ${successCount} cambios aplicados correctamente. Recuerda presionar el botón de guardar en el editor.`); // Forzar actualización visual del mapa W.map?.invalidate?.(); } else { alert("ℹ️ No hubo cambios para aplicar."); } } catch (error) { console.error('⛔ Error al aplicar cambios:', error); alert('Error al guardar cambios: ' + (error.message || error)); } finally { if (applyBtn) { applyBtn.disabled = false; applyBtn.textContent = 'Aplicar Cambios'; applyBtn.style.background = '#4CAF50'; } } } // Añadir pestaña al panel de scripts function addScriptToSettingsTab() { const tabName = 'Auto Name Places'; const tabSelector = `#user-tabs a[title="${tabName}"]`; if (document.querySelector(tabSelector)) return; const observer = new MutationObserver((mutations, obs) => { const settingsPanel = document.querySelector("#user-tabs"); if (settingsPanel) { obs.disconnect(); const newTab = document.createElement("li"); newTab.innerHTML = `<a href="#" title="${tabName}">${tabName}</a>`; settingsPanel.appendChild(newTab); newTab.querySelector('a').addEventListener("click", function(e) { e.preventDefault(); init(); }); } }); observer.observe(document.body, { childList: true, subtree: true }); } // Función de inicialización async function init() { try { await waitForWME(); const unnamedPlaces = getUnnamedPlaces(); if (!unnamedPlaces.length) { alert("No se encontraron Places sin nombre en el área actual."); return; } createApprovalTable(unnamedPlaces); } catch (error) { console.error('⛔ Error en init:', error); alert('Error al buscar places sin nombre: ' + (error.message || error)); } } // Iniciar script cuando WME esté listo waitForWME().then(() => { addScriptToSettingsTab(); }).catch(error => { console.error('⛔ Error al inicializar WME:', error); }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址