您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Select cart items based on layer rules with vertical and function selection and memory
// ==UserScript== // @name Ajuda Cart Batch Selector // @namespace http://tampermonkey.net/ // @version 0.8 // @description Select cart items based on layer rules with vertical and function selection and memory // @author MajaBukvic // @match https://ajuda.a2z.com/cms.html* // @grant none // ==/UserScript== (function() { 'use strict'; const COMMON_CONFIGS = { layers: { US_AE_JP_IN_TR_AU_SE_SG_DE: ['US', 'AE', 'JP', 'IN', 'TR', 'AU', 'SE', 'SG', 'DE'], TSE_Common: ['US', 'AE', 'EG', 'SA', 'AU', 'BE', 'IE', 'NL', 'PL', 'SE', 'SG', 'MX', 'BR', 'CA', 'ES', 'FR', 'IT', 'JP', 'DE', 'IN', 'TR', 'UK'] }, primaryLayers: { US_Only: ['US'], US_UK: ['US', 'UK'], TSE_Common: ['UK', 'AE', 'BE', 'MX', 'NL', 'PL', 'SE', 'TR'] }, secondaryLayers: { TSE_Common: ['US', 'AE', 'EG', 'SA', 'AU', 'BE', 'IE', 'NL', 'PL', 'SE', 'SG', 'MX', 'BR', 'CA', 'ES', 'FR', 'IT', 'JP', 'DE', 'IN', 'TR'] } }; const VERTICAL_CONFIGS = { TSI: { name: "Trust and Store Integrity (TSI)", functions: { SIV: { name: "Seller Identity Verification (SIV)", layers: ['US', 'AE', 'JP', 'IN', 'TR', 'AU', 'SA', 'SE', 'SG'], primaryLayers: COMMON_CONFIGS.primaryLayers.US_Only, secondaryLayers: ['AE', 'EG', 'SA', 'JP', 'IN', 'TR', 'AU', 'SE', 'SG'] }, IPV: { name: "In-person Verification (IPV)", layers: ['US', 'AE', 'DE', 'ES', 'MX', 'BE', 'FR', 'IN', 'IT', 'JP', 'KR', 'NL', 'PL', 'BR', 'SE', 'TH', 'TR', 'VN', 'CN', 'TW'], primaryLayers: COMMON_CONFIGS.primaryLayers.US_Only, secondaryLayers: ['AE', 'DE', 'ES', 'MX', 'BE', 'FR', 'IN', 'IT', 'JP', 'KR', 'NL', 'PL', 'BR', 'SE', 'TH', 'TR', 'VN', 'CN', 'TW'] }, TT: { name: "Transaction Trust (TT)", layers: ['US', 'ES', 'MX', 'SE', 'PL', 'CN', 'DE', 'FR', 'IT', 'JP', 'AE', 'NL', 'TR'], primaryLayers: COMMON_CONFIGS.primaryLayers.US_Only, secondaryLayers: ['ES', 'MX', 'SE', 'PL', 'CN', 'DE', 'FR', 'IT', 'JP', 'AE', 'NL', 'TR'] }, 'EU KYC': { name: "EU Know Your Customer (KYC)", layers: ['US', 'AE'], primaryLayers: COMMON_CONFIGS.primaryLayers.US_Only, secondaryLayers: ['AE', 'SA'] }, 'ROW KYC': { name: "ROW Know Your Customer (KYC)", layers: ['US', 'JP'], primaryLayers: COMMON_CONFIGS.primaryLayers.US_Only, secondaryLayers: ['JP'] }, SAM: { name: "Suspicious Activity Monitoring (SAM)", layers: COMMON_CONFIGS.layers.US_AE_JP_IN_TR_AU_SE_SG_DE, primaryLayers: COMMON_CONFIGS.primaryLayers.US_Only, secondaryLayers: ['UK', 'DE', 'AE', 'JP', 'IN', 'TR', 'AU', 'SE', 'SG'] }, DAC7: { name: "DAC7", layers: ['AE', 'AU', 'BE', 'BR', 'CA', 'DE', 'EG', 'ES', 'FR', 'IN', 'IT', 'JP', 'MX', 'NL', 'PL', 'SA', 'SE', 'SG', 'TR', 'US', 'UK'], primaryLayers: ['UK'], secondaryLayers: ['AE', 'AU', 'BE', 'BR', 'CA', 'DE', 'EG', 'ES', 'FR', 'IN', 'IT', 'JP', 'MX', 'NL', 'PL', 'SA', 'SE', 'SG', 'TR', 'US'] }, VAT: { name: "Value Added Tax (VAT)", layers: ['BE', 'BR', 'DE', 'EG', 'FR', 'IT', 'IN', 'TR', 'US', 'JP'], primaryLayers: ['US', 'JP'], secondaryLayers: ['BE', 'BR', 'DE', 'EG', 'FR', 'IT', 'IN', 'TR'] } } }, TSE: { name: "Trusted Seller Experience (TSE)", functions: { PQ: { name: "Product Quality (PQ)", layers: COMMON_CONFIGS.layers.TSE_Common, primaryLayers: COMMON_CONFIGS.primaryLayers.TSE_Common, secondaryLayers: COMMON_CONFIGS.secondaryLayers.TSE_Common }, RA: { name: "Reported Abuse (RA)", layers: COMMON_CONFIGS.layers.TSE_Common, primaryLayers: COMMON_CONFIGS.primaryLayers.TSE_Common, secondaryLayers: COMMON_CONFIGS.secondaryLayers.TSE_Common }, AtoZ: { name: "A-to-z Guarantee Claims seller-facing (Claims-seller)", layers: COMMON_CONFIGS.layers.TSE_Common, primaryLayers: COMMON_CONFIGS.primaryLayers.TSE_Common, secondaryLayers: COMMON_CONFIGS.secondaryLayers.TSE_Common }, SAP: { name: "Sales Abuse Prevention (SAP)", layers: COMMON_CONFIGS.layers.TSE_Common, primaryLayers: COMMON_CONFIGS.primaryLayers.TSE_Common, secondaryLayers: COMMON_CONFIGS.secondaryLayers.TSE_Common }, RPSA: { name: "Restricted Product Seller Appeals (RPSA)", layers: COMMON_CONFIGS.layers.TSE_Common, primaryLayers: COMMON_CONFIGS.primaryLayers.TSE_Common, secondaryLayers: COMMON_CONFIGS.secondaryLayers.TSE_Common }, PAT: { name: "Product Authentication Team (PAT)", layers: COMMON_CONFIGS.layers.TSE_Common, primaryLayers: COMMON_CONFIGS.primaryLayers.TSE_Common, secondaryLayers: COMMON_CONFIGS.secondaryLayers.TSE_Common }, CERT: { name: "Certification Team (CERT)", layers: COMMON_CONFIGS.layers.TSE_Common, primaryLayers: COMMON_CONFIGS.primaryLayers.TSE_Common, secondaryLayers: COMMON_CONFIGS.secondaryLayers.TSE_Common }, APAY_Seller: { name: "APAY Seller", layers: ['US', 'DE', 'ES', 'FR', 'IN', 'IT', 'JP', 'UK'], primaryLayers: ['UK', 'US'], secondaryLayers: ['US', 'DE', 'ES', 'FR', 'IN', 'IT', 'JP'] }, FP: { name: "Fraud Prevention (FP)", layers: COMMON_CONFIGS.layers.US_AE_JP_IN_TR_AU_SE_SG_DE, primaryLayers: COMMON_CONFIGS.primaryLayers.US_Only, secondaryLayers: ['UK', 'DE', 'FR'] } } }, Buyer: { name: "Buyer", functions: { CatalogRisk: { name: "Catalog Risk", layers: COMMON_CONFIGS.layers.US_AE_JP_IN_TR_AU_SE_SG_DE, primaryLayers: COMMON_CONFIGS.primaryLayers.US_UK, secondaryLayers: ['US', 'UK', 'DE', 'FR'] }, BuyerRiskInvestigations: { name: "Buyer Risk Investigations", layers: COMMON_CONFIGS.layers.US_AE_JP_IN_TR_AU_SE_SG_DE, primaryLayers: ['US', 'CA'], secondaryLayers: ['US', 'CA', 'MX'] } } } }; let selectedVertical = null; let selectedFunction = null; function saveSelections(vertical, func) { localStorage.setItem('selectedVertical', vertical); localStorage.setItem('selectedFunction', func); } function loadSelections() { return { vertical: localStorage.getItem('selectedVertical'), function: localStorage.getItem('selectedFunction') }; } function createBatchButton() { const button = document.createElement('button'); button.textContent = 'Batch Selector'; button.className = 'btn btn-info'; button.style.marginLeft = '5px'; const bulkOperations = document.querySelector('.bulk-operations'); if (bulkOperations) { const deleteButton = bulkOperations.querySelector('.btn-warning'); if (deleteButton) { deleteButton.parentNode.insertAdjacentElement('afterend', button); } else { bulkOperations.appendChild(button); } } button.addEventListener('click', handleBatchSelection); } function parseObjectId(text) { const match = text.match(/([^\/]+)\/Published\/([^\/]+)\/([^\/]+)/); return match ? { id: match[1], layer: match[2], locale: match[3] } : null; } function simulateClick(element) { if (!element) return; const event = new MouseEvent('click', { view: window, bubbles: true, cancelable: true }); element.dispatchEvent(event); } function groupBlurbs() { const rows = document.querySelectorAll('#version-list tbody tr'); const groups = {}; Array.from(rows).forEach(element => { const blurbName = element.querySelector('td:nth-child(2) div:first-child').textContent; const objInfo = parseObjectId(element.querySelector('.sub-text').textContent); if (objInfo && selectedFunction.layers.includes(objInfo.layer)) { if (!groups[blurbName]) { groups[blurbName] = { versions: [] }; } groups[blurbName].versions.push({ element: element, layer: objInfo.layer, locale: objInfo.locale, id: objInfo.id }); } }); return groups; } function selectBatch(isPrimary) { const groups = groupBlurbs(); const toSelect = new Set(); Object.entries(groups).forEach(([blurbName, group]) => { if (isPrimary) { // Primary selection: ONLY select primary layers selectedFunction.primaryLayers.forEach(layer => { const layerVersions = group.versions.filter(v => v.layer === layer); if (layerVersions.length > 0) { toSelect.add(layerVersions[0].element); } }); } else { // Secondary selection: select ALL layers in secondaryLayers, including primary layers if they're listed selectedFunction.secondaryLayers.forEach(layer => { const layerVersions = group.versions.filter(v => v.layer === layer); if (layerVersions.length > 0) { toSelect.add(layerVersions[0].element); } }); } }); // First uncheck all checkboxes document.querySelectorAll('#version-list tbody tr input[type="checkbox"]').forEach(checkbox => { if (checkbox.checked) simulateClick(checkbox); }); // Then select the ones we want toSelect.forEach(element => { let checkbox = element.querySelector('input[type="checkbox"]'); if (!checkbox.checked) simulateClick(checkbox); }); } function updateFunctionSelect(verticalKey) { const functionSelect = document.getElementById('functionSelect'); functionSelect.innerHTML = ''; const savedSelections = loadSelections(); if (verticalKey && VERTICAL_CONFIGS[verticalKey]) { const functions = VERTICAL_CONFIGS[verticalKey].functions; Object.entries(functions).forEach(([key, config]) => { const option = document.createElement('option'); option.value = key; option.textContent = config.name; if (savedSelections.function === key) { option.selected = true; } functionSelect.appendChild(option); }); functionSelect.disabled = false; selectedFunction = functions[savedSelections.function] || functions[Object.keys(functions)[0]]; } else { functionSelect.disabled = true; selectedFunction = null; } } function handleBatchSelection() { const dialog = document.createElement('div'); dialog.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border: 1px solid #ccc; box-shadow: 0 0 10px rgba(0,0,0,0.5); z-index: 1001; border-radius: 4px; min-width: 300px; `; const savedSelections = loadSelections(); let html = ` <div style="margin-bottom: 15px;"> <label for="verticalSelect">Select Vertical:</label> <select id="verticalSelect" class="form-control" style="margin-bottom: 10px;"> ${Object.entries(VERTICAL_CONFIGS).map(([key, config]) => `<option value="${key}" ${savedSelections.vertical === key ? 'selected' : ''}>${config.name}</option>` ).join('')} </select> <label for="functionSelect">Select Function:</label> <select id="functionSelect" class="form-control"> </select> </div> <div style="text-align: center;"> <button id="selectPrimary" class="btn btn-primary" style="margin: 5px;">Select Primary Batch</button><br> <button id="selectSecondary" class="btn btn-info" style="margin: 5px;">Select Secondary Batch</button><br> <button id="closeDialog" class="btn" style="margin: 5px;">Close</button> </div> `; dialog.innerHTML = html; document.body.appendChild(dialog); const verticalSelect = document.getElementById('verticalSelect'); updateFunctionSelect(savedSelections.vertical || verticalSelect.value); verticalSelect.onchange = (e) => { selectedVertical = VERTICAL_CONFIGS[e.target.value]; updateFunctionSelect(e.target.value); saveSelections(e.target.value, document.getElementById('functionSelect').value); }; document.getElementById('functionSelect').onchange = (e) => { const verticalKey = verticalSelect.value; selectedFunction = VERTICAL_CONFIGS[verticalKey].functions[e.target.value]; saveSelections(verticalKey, e.target.value); }; document.getElementById('selectPrimary').onclick = () => { if (selectedFunction) { selectBatch(true); dialog.remove(); } else { alert("Please select a vertical and function first."); } }; document.getElementById('selectSecondary').onclick = () => { if (selectedFunction) { selectBatch(false); dialog.remove(); } else { alert("Please select a vertical and function first."); } }; document.getElementById('closeDialog').onclick = () => { dialog.remove(); }; if (savedSelections.vertical) { selectedVertical = VERTICAL_CONFIGS[savedSelections.vertical]; selectedFunction = VERTICAL_CONFIGS[savedSelections.vertical].functions[savedSelections.function]; } else { selectedVertical = VERTICAL_CONFIGS[verticalSelect.value]; selectedFunction = VERTICAL_CONFIGS[verticalSelect.value].functions[document.getElementById('functionSelect').value]; } } if (window.location.href.includes('ajuda.a2z.com/cms.html')) { const observer = new MutationObserver((mutations, obs) => { const bulkOperations = document.querySelector('.bulk-operations'); if (bulkOperations) { createBatchButton(); obs.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); } })();