京东商品参数对比工具

该脚本可用于对比不限数量的同类型商品(如:手机、笔记本)的详细参数

// ==UserScript==
// @name         京东商品参数对比工具
// @namespace    http://tampermonkey.net/
// @version      20250710174232
// @description  该脚本可用于对比不限数量的同类型商品(如:手机、笔记本)的详细参数
// @author       Yihang Wang <[email protected]>
// @match        https://item.jd.com/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// ==/UserScript==
!function(){"use strict";function n(){const t=["join","sort","assign","length","基本信息_商品名称","665820fXUQHp","Polling timeout","indexOf","object","1mtEJny","44628881JJiqLZ","7215810RopYsY","4184637xyOmIK","isArray","7njQAmc","基本信息_商品编号","2406676FoeyWu","toString","12bjQrDW","13398980bbAlGq","5QDRemz","1112828MSOHbo","random","jd-price-compare-user-id","176jRaBKf"];return(n=function(){return t})()}function t(n,e="",o="_"){const a=r,s={};for(const r in n)if(n.hasOwnProperty(r)){const i=e?""+e+o+r:r;typeof n[r]!==a(194)||null===n[r]||Array[a(199)](n[r])?s[i]=n[r]:Object[a(213)](s,t(n[r],i,o))}return s}function e(n){const t=r,e=[t(215),t(201),"价格","图片","状态","备注"],o=e[t(193)](n);return-1!==o?o:e[t(214)]}function o(n=100,t=500){const e=r,o=Math.floor(Math[e(208)]()*(t-n+1))+n;return new Promise(n=>setTimeout(n,o))}function r(t,e){const o=n();return(r=function(n,t){return o[n-=192]})(t,e)}function a(n,t){const e=r;return[...n][e(212)]()[e(211)]("-")+"-"+t}!function(n){const t=r,e=n();for(;;)try{if(852214==-parseInt(t(195))/1*(-parseInt(t(207))/2)+-parseInt(t(198))/3+parseInt(t(202))/4*(-parseInt(t(206))/5)+-parseInt(t(197))/6*(-parseInt(t(200))/7)+parseInt(t(210))/8*(-parseInt(t(216))/9)+-parseInt(t(205))/10+parseInt(t(196))/11*(parseInt(t(204))/12))break;e.push(e.shift())}catch(n){e.push(e.shift())}}(n);const s=i;function i(n,t){const e=d();return(i=function(n,t){return e[n-=324]})(n,t)}!function(n){const t=i,e=n();for(;;)try{if(317478==parseInt(t(333))/1+-parseInt(t(332))/2*(-parseInt(t(324))/3)+parseInt(t(329))/4+parseInt(t(331))/5*(parseInt(t(334))/6)+parseInt(t(335))/7*(parseInt(t(325))/8)+parseInt(t(330))/9*(-parseInt(t(327))/10)+-parseInt(t(326))/11)break;e.push(e.shift())}catch(n){e.push(e.shift())}}(d);const c=s(328);function d(){const n=["11302335wtsfMf","20yPAxzt","20250710174232","939448xuOZkx","1625823IksVSJ","5RFXrtK","184dSgsUa","393112hyrpDY","1380024NsCwGI","3318805FPsaaP","12201mQZpop","8YsJFqC"];return(d=function(){return n})()}function l(){const n=["9Kigydf","[storage] saveItemToStorage","getItem","13254690JxdKwG","[storage] saveListToStorage","8cVHFxZ","7189236fhpzpu","stringify","toISOString","jd-compare-items","1037429mCyGSM","parse","1536484lyMxdV","7FbdGMM","3235347bpgTQF","6037700CZerGC","1896366IcIkem","setItem","push","log"];return(l=function(){return n})()}function p(n,t){const e=l();return(p=function(n,t){return e[n-=230]})(n,t)}function u(n,t,e,o=c){const r=p,a=JSON[r(230)](localStorage[r(241)](r(248))||"{}");a[n]={user_id:e,created_at:(new Date)[r(247)](),updated_at:(new Date).toISOString(),version:o,data:t},localStorage[r(236)](r(248),JSON[r(246)](a))}function m(n,t,e=c,o){const r=p,a=JSON.parse(localStorage[r(241)]("jd-compare-lists")||"[]"),s=o(n,t),i={id:s,user_id:t,created_at:(new Date).toISOString(),updated_at:(new Date)[r(247)](),version:e,items:n};return a[r(237)](i),localStorage[r(236)]("jd-compare-lists",JSON[r(246)](a)),s}function f(n,t){const e=v();return(f=function(n,t){return e[n-=298]})(n,t)}function g(n){const t=f;let e=window[t(424)][t(357)][t(404)](/\/(\d+)\.html/);return e&&e[1]?e[1]:t(340)}function b(n){const t=f,e=g(),o=[t(364)+e,t(365),t(429),t(372),t(383),t(366)];for(let e of o){const o=n.querySelector(e);if(o){const n=o.innerText[t(333)]()[t(404)](/[\d.]+/);if(n)return parseFloat(n[0])}}const r=n.querySelectorAll("*");for(let n of r){const e=n.innerText[t(333)]();if(e[t(371)]("¥")||e.includes("¥")){const n=e.match(/[\d.]+/);if(n)return parseFloat(n[0])}}return 0}function h(n){const t=f,e=n[t(393)](t(351)),o={};return e?(e[t(376)](".item")[t(316)](n=>{const e=t,r=n[e(393)](e(323)),a=n[e(393)](".text");if(!r||!a)return;const s=r[e(405)].trim(),i=a[e(405)][e(333)]();s&&i&&(o[s]=i)}),o):o}async function w(n){const t=f;try{let e=h(n),o=function(n){const t=f,e=n[t(376)](t(409)),o={};return e[t(316)](n=>{const e=t,r=n[e(393)]("h3")[e(405)][e(333)](),a={};n[e(376)]("dl")[e(316)](n=>{const t=e,o=n[t(393)]("dt")[t(405)][t(333)](),r=n[t(393)]("dd:not(.Ptable-tips)")[t(405)][t(333)]();a[o]=r}),o[r]=a}),o}(n),r=function(n){const t=f,e=[t(315),".goods-base .exclusive-row.item .text",".goods-base .item:last-child .text",t(362),t(358)];for(let o of e){const e=n[t(393)](o);if(e)return e[t(405)].trim()}const o=h(n);return o["包装清单"]?o["包装清单"]:t(344)}(n),a=function(n){const t=f,e=n[t(393)]("#spec-list > ul > li:nth-child(1) > img");if(!e)return"";let o=e[t(312)][t(399)]("/");return o[3]="n0",o[4]="jfs",o[5]="t1",o[t(391)]("/")}(n),s=g(),i=[];return n===window[t(420)]&&(await async function(n){const t=f;if(n===window[t(420)])return new Promise(e=>{const o=t;let r=0,a=!1;const s=new MutationObserver(()=>{const t=f;n.querySelector(t(411))&&(a=!0,s[t(321)](),setTimeout(e,500))});s[o(324)](n[o(396)],{childList:!0,subtree:!0}),function t(){const s=o;if(a)return;let i=n[s(396)].scrollHeight;window[s(392)](0,300),r+=300,r>=i-window.innerHeight?setTimeout(()=>{a||e()},1e3):setTimeout(t,200)}()})}(n),await async function(n,t=800){const e=f,o=n[e(393)](e(411))||n[e(393)](e(313));if(!o)return;const r=Array.from(o[e(376)](e(417)))[e(416)](n=>{const t=e;return n.getBoundingClientRect()[t(370)]+window[t(394)]});for(let n=0;n<r[e(335)];n++)window[e(388)]({top:r[n]-window.innerHeight/2,behavior:e(390)}),await new Promise(n=>setTimeout(n,t));window[e(388)]({top:document.body[e(410)],behavior:e(390)}),await new Promise(n=>setTimeout(n,1e3))}(n,800)),i=function(n){const t=f,e=new Set,o=[t(411),t(313),t(334),t(310),"#J-detail-bottom"];let r=[];if(o[t(316)](e=>{const o=t,a=n[o(393)](e);a&&r[o(379)](a)}),0===r[t(335)])return[];r.forEach(n=>{n.querySelectorAll('[style*="background-image"]').forEach(n=>{const t=f,o=n.getAttribute(t(304))[t(404)](/background-image:\s*url\((['"]?)(.*?)\1\)/);if(o&&o[2]){let n=o[2];n[t(346)]("//")&&(n=t(389)+n),e[t(378)](n)}})});const a=["img[data-lazy-img]",t(322),t(306),t(400)];r[t(316)](n=>{const o=t;n[o(376)](a[o(391)](",")).forEach(n=>{const t=o;let r=n.getAttribute(t(386))||n[t(326)](t(361))||n.getAttribute(t(403))||n.getAttribute(t(312));r&&r!==t(352)&&!r[t(328)](t(408))&&(r[t(346)]("//")&&(r=t(389)+r),r[t(346)]("/")&&(r=t(432)+r),e.add(r))})}),r[t(316)](n=>{const o=t;n[o(376)](o(417))[o(316)](n=>{const t=o,r=window.getComputedStyle(n)[t(342)].match(/url\([\"']?(.*?\.(jpg|jpeg|png|webp|gif|avif)(\?.*?)?)[\"']?\)/i);if(r&&r[1]){let n=r[1];n.startsWith("//")&&(n=t(389)+n),e[t(378)](n)}})});const s=Array[t(368)](e).filter(n=>/\.(jpg|jpeg|png|webp|gif|avif)(\?.*)?$/i[t(347)](n));return s[t(335)]>0&&s.forEach((n,t)=>{}),s}(n),i[t(335)],{"基本信息_商品编号":s,"基本信息":e,"主体信息":o,"包装信息":r,"价格":t(309),"图片":a,"详情图片":i,"备注":"","状态":"正常"}}catch(n){return{"基本信息_商品编号":g()||"unknown","基本信息":{},"主体信息":{},"包装信息":t(320),"价格":t(309),"图片":"","详情图片":[],"备注":"","状态":"正常","错误信息":n.message}}}async function I(n){if(n!=g())return async function(n){const t=f;await o(10,30);let e="https://item.jd.com/"+n+t(384);const r=await fetch(e);if(!r.ok)throw new Error(t(360)+r[t(421)]);const a=await r[t(319)]();return w((new DOMParser)[t(311)](a,t(418)))}(n);try{await function(n,t=100,e=50){return new Promise((o,a)=>{let s=0;!function i(){const c=r;n()?o():s<e?(s++,setTimeout(i,t)):a(new Error(c(192)))}()})}(()=>b(document)>0);let n=b(document),t=await w(document);return t["价格"]=n,t}catch(n){let t=await w(document);return t["价格"]=0,t}}function v(){const n=[" 的信息","https://item.jd.com","[parser] getMainInfo: 正在解析 ","[parser] getPrice: 使用选择器 ","[parser] getBasicInfo: ","[parser] getPackageList: 未找到包装清单信息","[parser] getMainInfo: "," 条基本信息","isArray","[parser] parseItem: 当前页面商品解析完成,价格: ","style","1684582NojKEv","img[data-src]","[parser] getBasicInfo: 共解析出 ","[parser] parseItem: 正在获取商品 ","N/A","#J-detail-top","parseFromString","src",".ssd-module-wrap","[parser] scrollThroughAllModules: 滚动到第 ",".package-list p","forEach","warn","[parser] scrollThroughAllModules: 未找到 .ssd-module-wrap","text","解析出错","disconnect","img[data-lazyload]",".name","observe","[parser] getPrice: 开始获取商品 ","getAttribute","[parser] parseItemWithDocument: 开始解析当前页面商品信息","endsWith"," 个相关商品ID","[parser] parseItemWithDocument: 商品信息解析完成","[parser] scrollAndWaitForDetailDiv: #J-detail-content > div.ssd-module-wrap 已出现,等待图片加载..."," 个主体信息分类","trim","#J-detail-content","length","[parser] getMainInfo: 共解析出 ","15759yXVrpy","[parser] getPrice: 从文本内容获取到价格: ","[parser] getPackageList: 使用选择器 ","unknown","px / ","backgroundImage","[parser] parseItem: 开始解析商品 ","暂无包装信息","[parser] getRelatedItemIDs: 共找到 ","startsWith","test"," 个颜色/规格选项","keys","product","#detail > div.tab-con > div:nth-child(3) > div.goods-base","img/e/blank.gif","[parser] colorSize:","colorSize"," 个详情图片 url","[parser] getImageUrl: 开始获取商品主图URL","href",'.goods-base .item:contains("包装") .text'," 的页面内容","HTTP error! Status: ","data-lazyload",'.goods-base .item:contains("包装清单") .text',"[parser] scrollAndWaitForDetailDiv: 已滚动: ",".price.J-p-",".price",".price-box .price","toString","from","log","top","includes",".p-price .price","[parser] getRelatedItemIDs: 开始获取相关商品ID列表","1155945RgEFbr","1AtEOMV","querySelectorAll","[parser] parseItemWithDocument: 未能提取到任何详情图片 url","add","push","error","[parser] getItemID: 从URL获取到商品ID: "," 部分",".sku-price",".html","52686jCiUyt","data-lazy-img","11447568qvhvng","scrollTo","https:","smooth","join","scrollBy","querySelector","pageYOffset","[parser] getBasicInfo: 开始解析商品基本信息","body","[parser] pageConfig:","[parser] getPrice: 无法获取商品价格","split","img[src]"," 获取到价格: ","707xftyto","data-src","match","textContent","[parser] getPackageList: 开始获取商品包装清单","[parser] getMainInfo: 开始解析商品主体信息","/blank.gif",".Ptable-item","scrollHeight","#J-detail-content > div.ssd-module-wrap","[parser] getDetailImageUrls: 共提取到 ","[parser] parseItem: 等待价格超时,继续处理其他信息","8whUqSP"," 的价格","map",".ssd-module","text/html","[parser] getDetailImageUrls: 未找到详情区元素","document","status"," 个 .ssd-module","3726200STtMQx","location","[parser] getItemID: 无法从URL获取商品ID","values","[parser] scrollAndWaitForDetailDiv: 已滚动到底部,等待内容加载...","3130gkrIKC",".jd-price","295345rxFiXL"];return(v=function(){return n})()}function x(){const n=["#preview > div.preview-info","className"," - "," 个型号","div","1031924tnSVYB","添加本商品","color","padding","jd-price-compare-add-all-button","onClick","13512696JtbwgX","open","textContent","length","4px","jd-price-compare-add-single-button","appendChild","\n        position: fixed;\n        top: 20px;\n        right: 20px;\n        background: white;\n        padding: 15px;\n        border-radius: 8px;\n        box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n        z-index: 9999;\n        min-width: 300px;\n    ","backgroundColor","margin-bottom: 10px;font-weight: bold;color: #333;","none","mouseout","margin-top: 5px;text-align: center;color: #666;font-size: 12px;","inline-block","开始对比 (","jd-price-compare-status-line-div","[ui] createCompareButtons: 创建对比按钮组","gap","addEventListener","#fff","jd-price-add-feedback-button","添加所有 ","16px","preventDefault","京东商品参数对比工具 v","#4a90e2","120px","#357abd","fill","8px 16px","display","正在添加商品...","parentNode","click","#000000","assign","70dyNhFy","cssText","forEach","center","jd-price-compare-start-button","pointer","3148960EYEuGz",")详情...","insertBefore","[ui] updateCompareButton","125964aEPxpv","4292370LksTMH","body","style","21IKrGlG","justifyContent","text","1059843mARQvv","正在获取商品(ID:","background-color 0.3s","[ui] updateProgress","createElement","textAlign",".goods-base","11UvNzvg","log","[ui] addStatusLine: 添加状态栏","#detail > div.tab-con","compare-buttons","#detail","nextSibling","1870830cjwCfU","mouseover","9gEJLTq","width: 0%;height: 100%;background: #4a90e2;transition: width 0.3s ease;","href","getElementById","25aageqe"];return(x=function(){return n})()}function y(n,t,e,o){const r=j,a=t/e*100;n[r(388)][r(324)].width=a+"%",n[r(327)].textContent=t+"/"+e+r(351)+o}function k(n){const t=j;let e=document[t(347)](t(315)),o=n("jd-price-compare-item-ids",[]);e&&(e.textContent="开始对比 ("+o[t(363)]+")")}function j(n,t){const e=x();return(j=function(n,t){return e[n-=304]})(n,t)}function S(){const n=["344139niClDn","[compare] createList: 创建对比列表","4bRyFUL","from"," 的详情","style","jd-price-compare-item-ids","2220xspTmP",'</a>\n                    <div class="btn-group btn-group-sm">\n                        <button class="btn btn-outline-secondary btn-hide" data-index="',"6450336mlESFJ","[compare] appendList: 添加完成","</textarea>\n                </div>","type","src","localeCompare",'<div class="text-center">\n                    <img src="','.html" target="_blank" \n                        class="text-primary text-decoration-none me-2">',"document","[compare] addAllItems: 添加商品 ","N/A","当前待对比商品列表为空,请先点击添加商品按钮。","9MYVxTD","179718mSLVfp","toLocaleString","appendChild",'<div class="notes-container">\n                    <textarea class="form-control notes-input" data-index="',"jd-price-compare-status-line","title","text/javascript","values","\n            // 图片弹窗逻辑\n            document.addEventListener('click', function(e) {\n                if (e.target.classList.contains('popup-image')) {\n                    var modal = document.getElementById('image-popup-modal');\n                    var img = document.getElementById('image-popup-img');\n                    img.src = e.target.src;\n                    modal.style.display = 'flex';\n                }\n            });\n            document.getElementById('image-popup-close').onclick = function() {\n                document.getElementById('image-popup-modal').style.display = 'none';\n            };\n            document.getElementById('image-popup-modal').onclick = function(e) {\n                if (e.target === this) this.style.display = 'none';\n            };\n        ",'\n    <div id="image-popup-modal" style="display:none;position:fixed;z-index:9999;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,0.7);align-items:center;justify-content:center;">\n        <span id="image-popup-close" style="position:absolute;top:30px;right:50px;font-size:2.5rem;color:#fff;cursor:pointer;z-index:10001;">&times;</span>\n        <img id="image-popup-img" src="" style="max-width:90vw;max-height:90vh;box-shadow:0 0 20px #000;z-index:10000;" />\n    </div>','" \n                        class="img-fluid product-image popup-image" style="max-height: 200px; object-fit: contain; cursor: pointer;">\n                </div>',"filter","replace",";\n                let csvRows = ['sku,url'];\n                currentItemIds.forEach(function(itemId) {\n                    const item = items[itemId];\n                    if (!item) return;\n                    var sku = item.data['基本信息_商品编号'] || '';\n                    var urls = item.data['详情图片'] || [];\n                    if (Array.isArray(urls)) {\n                        urls.forEach(function(url) {\n                            csvRows.push(sku + ',' + url);\n                        });\n                    }\n                });\n                var BOM = '\\uFEFF';\n                var csvContent = BOM + csvRows.join('\\n');\n                var blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8' });\n                var link = document.createElement('a');\n                link.href = URL.createObjectURL(blob);\n                link.download = 'image-urls.csv';\n                link.style.display = 'none';\n                document.body.appendChild(link);\n                link.click();\n                document.body.removeChild(link);\n            });\n        });\n    ","keys","72037hQvYbi","添加商品失败,请稍后重试","</span>","发生错误,请重试","</th>","354XKDJfZ",".csv';\n                    link.style.display = 'none';\n                    document.body.appendChild(link);\n                    link.click();\n                    document.body.removeChild(link);\n                }\n            });\n\n            document.getElementById('exportImageUrlsBtn').addEventListener('click', function() {\n                const items = JSON.parse(localStorage.getItem('jd-compare-items') || '{}');\n                const currentItemIds = ","remove","[compare] appendList: 添加商品失败:","详情图片","https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js","对比完成,已打开商品对比结果页面。","3655165zMppYk","<th>","log","1390400kqfGKH","bg-success",'<span class="badge ',"textContent","已成功添加 ","[compare] appendList: 添加商品到对比列表","383PWTvFj","container","基本信息_商品名称","[compare] createList: 对比列表为空,无法创建","join","bg-secondary","getElementById","data","\n        $(document).ready(function() {\n            const table = $('#compare-result').DataTable({\n                language: {\n                    url: '//cdn.datatables.net/plug-ins/1.13.7/i18n/zh.json'\n                },\n                pageLength: 25,\n                order: [[0, 'asc']],\n                responsive: true,\n                scrollX: true,\n                scrollY: '60vh',\n                scrollCollapse: true,\n                fixedHeader: true,\n                columnDefs: [\n                    {\n                        targets: '图片',\n                        orderable: false\n                    },\n                    {\n                        targets: '备注',\n                        orderable: false\n                    }\n                ],\n                dom: '<\"row\"<\"col-sm-12 col-md-6\"l><\"col-sm-12 col-md-6\"f>>' +\n                     '<\"row\"<\"col-sm-12\"tr>>' +\n                     '<\"row\"<\"col-sm-12 col-md-5\"i><\"col-sm-12 col-md-7\"p>>',\n                initComplete: function() {\n                    $('.dataTables_length select').addClass('form-select');\n                    $('.dataTables_filter input').addClass('form-control');\n                }\n            });\n\n            $(document).on('click', '.btn-hide', function() {\n                const index = $(this).data('index');\n                const row = table.row(index);\n                const statusCell = row.cell(function(idx, data, node) {\n                    return $(node).find('.badge').length > 0;\n                });\n                const currentStatus = statusCell.data();\n                const newStatus = currentStatus === '隐藏' ? '正常' : '隐藏';\n                statusCell.data(newStatus);\n                statusCell.html('<span class=\"badge ' + (newStatus === '隐藏' ? 'bg-secondary' : 'bg-success') + '\">' + newStatus + '</span>');\n                $(this).toggleClass('active');\n                const items = JSON.parse(localStorage.getItem('jd-compare-items') || '{}');\n                const itemId = row.data()[0].match('/href=\".*/(d+).html\"/')[1];\n                if (items[itemId]) {\n                    items[itemId].data.状态 = newStatus;\n                    localStorage.setItem('jd-compare-items', JSON.stringify(items));\n                }\n            });\n\n            $(document).on('click', '.btn-alternative', function() {\n                const index = $(this).data('index');\n                const row = table.row(index);\n                const statusCell = row.cell(function(idx, data, node) {\n                    return $(node).find('.badge').length > 0;\n                });\n                const currentStatus = statusCell.data();\n                const newStatus = currentStatus === '备选' ? '正常' : '备选';\n                statusCell.data(newStatus);\n                statusCell.html('<span class=\"badge ' + (newStatus === '备选' ? 'bg-info' : 'bg-success') + '\">' + newStatus + '</span>');\n                $(this).toggleClass('active');\n                const items = JSON.parse(localStorage.getItem('jd-compare-items') || '{}');\n                const itemId = row.data()[0].match('/href=\".*/(d+).html\"/')[1];\n                if (items[itemId]) {\n                    items[itemId].data.状态 = newStatus;\n                    localStorage.setItem('jd-compare-items', JSON.stringify(items));\n                }\n            });\n\n            $(document).on('change', '.notes-input', function() {\n                const index = $(this).data('index');\n                const row = table.row(index);\n                const note = $(this).val();\n                const items = JSON.parse(localStorage.getItem('jd-compare-items') || '{}');\n                const itemId = row.data()[0].match('/href=\".*/(d+).html\"/')[1];\n                if (items[itemId]) {\n                    items[itemId].data.备注 = note;\n                    localStorage.setItem('jd-compare-items', JSON.stringify(items));\n                }\n            });\n\n            document.getElementById('exportCsvBtn').addEventListener('click', function() {\n                const table = document.getElementById('compare-result');\n                const rows = table.querySelectorAll('tr');\n                let csv = [];\n                const BOM = '\\uFEFF';\n                for (let i = 0; i < rows.length; i++) {\n                    const row = [], cols = rows[i].querySelectorAll('td, th');\n                    for (let j = 0; j < cols.length; j++) {\n                        let text = cols[j].innerText;\n                        if (text.includes(',') || text.includes('\"') || text.includes('\\n')) {\n                            text = '\"' + text.replace(/\"/g, '\"\"') + '\"';\n                        }\n                        row.push(text);\n                    }\n                    csv.push(row.join(','));\n                }\n                const csvContent = BOM + csv.join('\\n');\n                const blob = new Blob([csvContent], { \n                    type: 'text/csv;charset=utf-8'\n                });\n                const link = document.createElement('a');\n                if (window.navigator.msSaveOrOpenBlob) {\n                    window.navigator.msSaveOrOpenBlob(blob, '"," 个商品的对比列表","正在创建 ","所有商品已添加完成","1296YJAwzp","color","添加失败","script","forEach","open","\n            </tr>\n        ","[compare] addAllItems: 批量添加所有商品","map",".csv');\n                } else {\n                    link.href = URL.createObjectURL(blob);\n                    link.download = '",'" alt="',"基本信息_商品编号","body","close","head","_blank","正在获取商品 ","<td>","size","error"," 个待对比商品","length"," 个商品的对比列表..."];return(S=function(){return n})()}function C(n,o){const r=B,a=o[r(503)](n=>function(n){const t=p;return JSON.parse(localStorage[t(241)](t(248))||"{}")[n]}(n)).filter(Boolean);if(0===a[r(516)])return void alert("没有找到可对比的商品数据");const s=new Set;a[r(499)](n=>{const e=r,o=t(n.data);Object[e(461)](o)[e(499)](n=>s.add(n))});const i=Array[r(521)](s).sort((n,t)=>{const o=r,a=e(n),s=e(t);return a!==s?a-s:n[o(532)](t)}),d=a[r(503)]((n,e)=>{const o=r,a=t(n[o(490)]);return i.map(n=>{const t=o;if(n===t(471))return null;if("图片"===n)return t(533)+(a[n]||"")+t(505)+(a[t(485)]||"")+t(457);if(n===t(506))return'<div class="d-flex align-items-center">\n                    <a href="https://item.jd.com/'+a[n]+t(534)+(a[n]||"")+t(526)+e+'">\n                            <i class="fas fa-eye-slash"></i>\n                        </button>\n                        <button class="btn btn-outline-info btn-alternative" data-index="'+e+'">\n                            <i class="fas fa-star"></i>\n                        </button>\n                    </div>\n                </div>';if("价格"===n){const e=a[n];return e===t(444)?'<span class="text-muted">N/A</span>':'<span class="text-danger fw-bold">¥'+e+"</span>"}if("备注"===n)return t(450)+e+'" \n                        placeholder="添加备注...">'+(a[n]||"")+t(529);if("状态"===n){const e=a[n]||"正常";let o=t(478);return"隐藏"===e&&(o=t(488)),"备选"===e&&(o="bg-info"),t(479)+o+'">'+e+t(464)}return a[n]||""})[o(458)](n=>null!==n)}),l=i[r(458)](n=>n!==r(471)),u=r(491)+n+r(504)+n+r(468)+JSON.stringify(o)+r(460);let m='<!DOCTYPE html>\n<html>\n<head>\n    <meta charset="UTF-8">\n    <meta name="viewport" content="width=device-width, initial-scale=1.0">\n    <title>商品对比 - 京东商品参数对比工具</title>\n    \x3c!-- Bootstrap CSS --\x3e\n    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">\n    \x3c!-- DataTables CSS --\x3e\n    <link href="https://cdn.datatables.net/1.13.7/css/dataTables.bootstrap5.min.css" rel="stylesheet">\n    \x3c!-- Font Awesome --\x3e\n    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">\n    <style>\n        :root {\n            --primary-color: #4a90e2;\n            --secondary-color: #357abd;\n            --success-color: #28a745;\n            --danger-color: #dc3545;\n            --warning-color: #ffc107;\n            --info-color: #17a2b8;\n            --light-color: #f8f9fa;\n            --dark-color: #343a40;\n        }\n\n        body {\n            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n            background-color: #f8f9fa;\n            color: #333;\n            line-height: 1.6;\n        }\n\n        .container {\n            max-width: 1400px;\n            padding: 2rem;\n        }\n\n        .header {\n            background: white;\n            padding: 2rem;\n            border-radius: 10px;\n            box-shadow: 0 2px 15px rgba(0,0,0,0.1);\n            margin-bottom: 2rem;\n        }\n\n        .metadata {\n            background: white;\n            padding: 1.5rem;\n            border-radius: 10px;\n            box-shadow: 0 2px 15px rgba(0,0,0,0.1);\n            margin-bottom: 2rem;\n        }\n\n        .metadata table {\n            margin-bottom: 0;\n        }\n\n        .metadata th {\n            background-color: #f8f9fa;\n            font-weight: 600;\n        }\n\n        .table-container {\n            background: white;\n            padding: 1.5rem;\n            border-radius: 10px;\n            box-shadow: 0 2px 15px rgba(0,0,0,0.1);\n            margin-bottom: 2rem;\n        }\n\n        .dataTables_wrapper {\n            padding: 1rem 0;\n        }\n\n        .dataTables_filter input {\n            border: 1px solid #dee2e6;\n            border-radius: 4px;\n            padding: 0.375rem 0.75rem;\n        }\n\n        .dataTables_length select {\n            border: 1px solid #dee2e6;\n            border-radius: 4px;\n            padding: 0.375rem 2rem 0.375rem 0.75rem;\n        }\n\n        .table {\n            margin-bottom: 0;\n        }\n\n        .table th {\n            background-color: #f8f9fa;\n            font-weight: 600;\n            white-space: nowrap;\n            position: sticky;\n            top: 0;\n            z-index: 1;\n        }\n\n        .table td {\n            vertical-align: middle;\n        }\n\n        .product-image {\n            transition: transform 0.3s ease;\n        }\n\n        .product-image:hover {\n            transform: scale(1.1);\n        }\n\n        .btn-export {\n            background-color: var(--primary-color);\n            color: white;\n            border: none;\n            padding: 0.5rem 1rem;\n            border-radius: 5px;\n            transition: background-color 0.3s ease;\n        }\n\n        .btn-export:hover {\n            background-color: var(--secondary-color);\n            color: white;\n        }\n\n        .faq {\n            background: white;\n            padding: 2rem;\n            border-radius: 10px;\n            box-shadow: 0 2px 15px rgba(0,0,0,0.1);\n        }\n\n        .faq h3 {\n            color: var(--dark-color);\n            margin-bottom: 1.5rem;\n            font-weight: 600;\n        }\n\n        .faq .question {\n            color: var(--primary-color);\n            font-weight: 600;\n            margin: 1rem 0 0.5rem;\n        }\n\n        .faq .answer {\n            color: #666;\n            margin-bottom: 1rem;\n        }\n\n        .faq .solution {\n            background-color: #f8f9fa;\n            padding: 1rem;\n            border-radius: 5px;\n            margin-top: 1rem;\n        }\n\n        .faq .solution li {\n            margin-bottom: 0.5rem;\n        }\n\n        .badge {\n            font-size: 0.875rem;\n            padding: 0.5em 0.75em;\n        }\n\n        .badge-version {\n            background-color: var(--info-color);\n            color: white;\n        }\n\n        .badge-count {\n            background-color: var(--success-color);\n            color: white;\n        }\n\n        @media (max-width: 768px) {\n            .container {\n                padding: 1rem;\n            }\n            \n            .header, .metadata, .table-container, .faq {\n                padding: 1rem;\n            }\n        }\n\n        .notes-container {\n            position: relative;\n        }\n        .notes-input {\n            width: 100%;\n            min-height: 60px;\n            resize: vertical;\n        }\n        .btn-hide, .btn-alternative {\n            padding: 0.25rem 0.5rem;\n        }\n        .btn-hide:hover {\n            background-color: #6c757d;\n            color: white;\n        }\n        .btn-alternative:hover {\n            background-color: #0dcaf0;\n            color: white;\n        }\n        .btn-alternative.active {\n            background-color: #0dcaf0;\n            color: white;\n        }\n        .btn-hide.active {\n            background-color: #6c757d;\n            color: white;\n        }\n    </style>\n</head>\n<body>\n    <div class="container">\n        <div class="header">\n            <div class="d-flex justify-content-between align-items-center">\n                <h1 class="mb-0">京东商品参数对比</h1>\n                <div>\n                    <span class="badge badge-version me-2">v{{version}}</span>\n                    <span class="badge badge-count">{{itemCount}} 个商品</span>\n                </div>\n            </div>\n        </div>\n        <div class="metadata">\n            <h2 class="h4 mb-3">列表信息</h2>\n            <div class="table-responsive">\n                <table class="table table-bordered">\n                    <thead>\n                        <tr>\n                            <th>列表 ID</th>\n                            <th>商品数量</th>\n                            <th>生成时间</th>\n                            <th>当前版本</th>\n                            <th>操作</th>\n                        </tr>\n                    </thead>\n                    <tbody>\n                        <tr>\n                            <td><code>{{listId}}</code></td>\n                            <td>{{itemCount}}</td>\n                            <td>{{now}}</td>\n                            <td>v{{version}}</td>\n                            <td>\n                                <button class="btn btn-export" id="exportCsvBtn">\n                                    <i class="fas fa-download me-1"></i>导出为 CSV\n                                </button>\n                                <button class="btn btn-export" id="exportImageUrlsBtn" style="margin-left: 8px;">\n                                    <i class="fas fa-download me-1"></i>导出图片URL\n                                </button>\n                            </td>\n                        </tr>\n                    </tbody>\n                </table>\n            </div>\n        </div>\n        <div class="table-container">\n            <h2 class="h4 mb-3">商品参数对比结果</h2>\n            <div class="alert alert-info">\n                <i class="fas fa-info-circle me-2"></i>\n                您可以点击列名来对当前列的商品信息进行排序,使用搜索框对商品参数进行搜索,精准定位商品信息。\n            </div>\n            <div class="table-responsive">\n                <table id="compare-result" class="table table-striped table-hover">\n                    <thead>\n                        <tr>\n                            {{tableHead}}\n                        </tr>\n                    </thead>\n                    <tbody>\n                        {{tableBody}}\n                    </tbody>\n                </table>\n            </div>\n        </div>\n        <div class="faq">\n            <h3><i class="fas fa-question-circle me-2"></i>常见问题</h3>\n            <h4 class="h5">关于价格显示"N/A"的说明</h4>\n            <p class="question">为什么价格显示为 N/A?</p>\n            <p class="answer">这是因为京东页面的限制,本脚本仅能在您点击"添加本商品"按钮时,获取到当前页面的商品价格。因此,当您使用"添加所有 XX 个型号"按钮时,只有当前页面显示的商品价格可以被成功获取。</p>\n            <div class="solution">\n                <h5 class="h6 mb-3"><i class="fas fa-lightbulb me-2"></i>解决方案</h5>\n                <ul class="mb-0">\n                    <li>大部分商家都会在商品的主图上标记价格,您可以通过仔细查看"图片"列来获取商品价格。</li>\n                    <li>为了获取更准确的价格信息,建议您不要使用"添加所有 XX 个型号"按钮,而是逐个点击商品详情页,并使用"添加本商品"按钮来获取价格。</li>\n                </ul>\n            </div>\n        </div>\n    </div>\n    \x3c!-- jQuery --\x3e\n    <script src="https://code.jquery.com/jquery-3.7.0.min.js"><\/script>\n    \x3c!-- Bootstrap Bundle with Popper --\x3e\n    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"><\/script>\n    \x3c!-- DataTables --\x3e\n    <script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"><\/script>\n    <script src="https://cdn.datatables.net/1.13.7/js/dataTables.bootstrap5.min.js"><\/script>\n    <script>\n        {{tableScript}}\n    <\/script>\n</body>\n</html> '[r(459)](/\{\{version\}\}/g,c).replace(/\{\{itemCount\}\}/g,a[r(516)])[r(459)](/\{\{listId\}\}/g,n)[r(459)](/\{\{now\}\}/g,(new Date)[r(448)]()).replace(/\{\{tableHead\}\}/g,l[r(503)](n=>r(475)+n+r(466)).join(""))[r(459)](/\{\{tableBody\}\}/g,d.map(n=>"\n            <tr>\n                "+n[r(503)](n=>r(512)+n+"</td>").join("")+r(501))[r(487)](""))[r(459)](/\{\{tableScript\}\}/g,u);m+=r(456);const f=window[r(500)]("",r(510));f[r(535)].write(m),f[r(535)][r(508)]();const g=f[r(535)].createElement(r(498));g[r(531)]=r(472),g.onload=function(){const n=r,t=f[n(535)].createElement("script");t[n(530)]=n(453),t[n(480)]=u+n(455),f[n(535)][n(507)][n(449)](t)},f[r(535)][r(509)][r(449)](g)}function B(n,t){const e=S();return(B=function(n,t){return e[n-=444]})(n,t)}async function A(n,t,e,o,r,a,s){const i=B;try{e(n,await t(n),s,a);let c=o(i(524),[]),d=new Set(c);d.add(n),r(i(524),Array[i(521)](d[i(454)]()));let l=document[i(489)](i(451));l&&(l.textContent=i(481)+d[i(513)]+i(515))}catch(n){let t=document.getElementById(i(451));throw t&&(t[i(480)]=i(463)),n}}!function(n){const t=p,e=n();for(;;)try{if(612501==parseInt(t(249))/1+-parseInt(t(235))/2+parseInt(t(239))/3*(-parseInt(t(231))/4)+-parseInt(t(234))/5+-parseInt(t(245))/6*(-parseInt(t(232))/7)+parseInt(t(244))/8*(parseInt(t(233))/9)+parseInt(t(242))/10)break;e.push(e.shift())}catch(n){e.push(e.shift())}}(l),function(n){const t=f,e=n();for(;;)try{if(499537==-parseInt(t(375))/1*(parseInt(t(305))/2)+-parseInt(t(374))/3+-parseInt(t(414))/4*(parseInt(t(430))/5)+-parseInt(t(385))/6*(-parseInt(t(402))/7)+parseInt(t(423))/8+parseInt(t(337))/9*(-parseInt(t(428))/10)+parseInt(t(387))/11)break;e.push(e.shift())}catch(n){e.push(e.shift())}}(v),function(n){const t=j,e=n();for(;;)try{if(753381==parseInt(t(328))/1+-parseInt(t(321))/2*(-parseInt(t(344))/3)+-parseInt(t(354))/4*(parseInt(t(348))/5)+-parseInt(t(322))/6+-parseInt(t(325))/7*(-parseInt(t(317))/8)+parseInt(t(342))/9*(parseInt(t(311))/10)+-parseInt(t(335))/11*(parseInt(t(360))/12))break;e.push(e.shift())}catch(n){e.push(e.shift())}}(x),function(n){const t=B,e=n();for(;;)try{if(551367==-parseInt(t(483))/1*(-parseInt(t(525))/2)+-parseInt(t(518))/3+-parseInt(t(520))/4*(-parseInt(t(474))/5)+-parseInt(t(467))/6*(-parseInt(t(462))/7)+-parseInt(t(527))/8*(-parseInt(t(446))/9)+-parseInt(t(477))/10+-parseInt(t(447))/11*(parseInt(t(495))/12))break;e.push(e.shift())}catch(n){e.push(e.shift())}}(S);const D=E;function E(n,t){const e=T();return(E=function(n,t){return e[n-=348]})(n,t)}function T(){const n=["firstChild","product","random","7296372vrjVfW","31103650QeYXNC","9yqAxlt","insertBefore","createElement","1565264HOkkbA","16px","load","GM_getValue","toString","8241552dDFYWS","jd-price-compare-user-id","marginBottom","#choose-btns > div","div","1435758ptjHKn","2098614AwJvMe","812FzNGPP","1781CpbrZk","5iqJQVS","style"];return(T=function(){return n})()}!function(n){const t=E,e=n();for(;;)try{if(879110==-parseInt(t(371))/1*(-parseInt(t(370))/2)+parseInt(t(355))/3*(-parseInt(t(358))/4)+-parseInt(t(348))/5*(parseInt(t(368))/6)+parseInt(t(369))/7+-parseInt(t(363))/8+-parseInt(t(353))/9+parseInt(t(354))/10)break;e.push(e.shift())}catch(n){e.push(e.shift())}}(T),window.addEventListener(D(360),function(){const n=E,t=c,e=window[n(361)],r=window.GM_setValue,s=function(n,t){const e=E;let o=n(e(364),"");return""==o&&(o=Math[e(352)]()[e(362)](36).substring(2),t(e(364),o)),o}(e,r);let i=e("jd-price-compare-item-ids",[]);!function(n,t=20,e=200){let o=0;!function r(){const a=E;pageConfig&&pageConfig[a(351)]&&pageConfig[a(351)].colorSize?n():o<t?(o++,setTimeout(r,e)):n()}()}(()=>{const d=n;let l=function(n,t){const e=f;var o=[g()];const r=t&&t[e(350)]&&t[e(350)][e(354)];if(r){const n=Array[e(302)](r)?r:Object[e(426)](r);n.length>0&&n[e(316)](function(n){const t=e;n&&n.skuId&&o[t(379)](n.skuId[t(367)]())})}let a=new Set(o);return Array[e(368)](a[e(426)]())}(document,pageConfig);!function(n=c){const t=j;let e=document[t(332)]("p");e.id="jd-price-compare-status-line",e[t(324)][t(356)]=t(309),e[t(324)][t(357)]="3px",e.textContent=t(384)+n;let o=document.createElement("div");o.id=t(375),o[t(324)][t(333)]=t(314),o.appendChild(e);let r=[t(349),t(338),t(340),t(334)],a=null;for(let n of r)if(a=document.querySelector(n),a)break;a?a[t(307)][t(319)](o,a[t(341)]):document[t(323)][t(366)](o)}(t);const p=function({getItemID:n,appendList:t,updateCompareButton:e,addAllItems:o,createList:r,relatedItemIDs:a,itemIDs:s,GM_getValue:i,version:d=c}){const l=j,p=document.createElement(l(353));p[l(350)]=l(339),p.style[l(305)]="flex",p[l(324)][l(326)]="center",p[l(324)][l(377)]="10px";const u={fontSize:l(382),padding:l(304),borderRadius:l(364),cursor:l(316),border:l(370),color:l(379),backgroundColor:"#4a90e2",transition:l(330),textDecoration:l(370),display:l(373),textAlign:l(314),minWidth:l(386)};return[{id:l(365),text:l(355),onClick:async function(o){const r=l;o[r(383)]();let a=n(document);document[r(347)]("jd-price-compare-status-line")[r(362)]=r(329)+a+r(318),await t(a),e(i)}},{id:l(358),text:l(381)+a[l(363)]+l(352),onClick:async function(n){n.preventDefault(),await o()}},{id:l(315),text:l(374)+s[l(363)]+")",onClick:function(n){n[l(383)](),r()}},{id:l(380),text:"意见反馈",onClick:function(n){const t=l;n[t(383)](),window[t(361)]("https://greasyfork.org/zh-CN/scripts/486915-%E4%BA%AC%E4%B8%9C%E5%95%86%E5%93%81%E5%8F%82%E6%95%B0%E5%AF%B9%E6%AF%94%E5%B7%A5%E5%85%B7/feedback")}}][l(313)](n=>{const t=l,e=document.createElement("a");e[t(346)]="javascript:void(0);",e.id=n.id,e.textContent=n[t(327)],Object[t(310)](e[t(324)],u),e.addEventListener(t(343),()=>{const n=t;e[n(324)][n(368)]=n(387)}),e[t(378)](t(371),()=>{const n=t;e[n(324)].backgroundColor=n(385)}),e[t(378)](t(308),n[t(359)]),p[t(366)](e)}),p}({getItemID:g,appendList:n=>A(n,I,u,e,r,t,s),updateCompareButton:()=>k(e),addAllItems:()=>async function(n,t){const e=B,r=function(){const n=j,t=document[n(332)]("div");t[n(324)][n(312)]=n(367);const e=document[n(332)](n(353));e[n(324)][n(312)]=n(369),e[n(362)]=n(306);const o=document.createElement(n(353));o[n(324)].cssText="width: 100%;height: 20px;background: #f0f0f0;border-radius: 10px;overflow: hidden;";const r=document[n(332)](n(353));r[n(324)][n(312)]=n(345);const a=document.createElement("div");return a[n(324)][n(312)]=n(372),o[n(366)](r),t[n(366)](e),t[n(366)](o),t.appendChild(a),document.body[n(366)](t),{container:t,fill:r,text:a,title:e}}();document[e(489)]("jd-price-compare-status-line");try{for(let a=0;a<n[e(516)];a++){const s=n[a];y(r,a+1,n[e(516)],e(511)+s+e(522));try{await t(s),a<n.length-1&&await o(20,40)}catch(n){await o(30,50)}}r[e(452)].textContent="添加完成!",y(r,n[e(516)],n[e(516)],e(494)),setTimeout(()=>{const n=e;r.container[n(469)]()},3e3)}catch(t){r.title[e(480)]=e(497),r[e(452)][e(523)][e(496)]="#ff4444",y(r,n[e(516)],n.length,e(465)),setTimeout(()=>{const n=e;r[n(484)][n(469)]()},5e3)}}(l,n=>A(n,I,u,e,r,t,s)),createList:()=>function(n,t,e,o,r,s){const i=B;let d=n("jd-price-compare-item-ids",[]),l=document[i(489)]("jd-price-compare-status-line");0!=d[i(516)]?(l&&(l.textContent=i(493)+d[i(516)]+i(517)),e(t(d,s,c,a),d),o(i(524),[]),l&&(l.textContent=i(473))):l&&(l[i(480)]=i(445))}(e,m,C,r,0,s),relatedItemIDs:l,itemIDs:i,GM_getValue:e,version:t}),b=document.querySelector(d(366));if(b){const n=document[d(357)](d(367));n[d(349)][d(365)]=d(359),n[d(349)].textAlign="center",n.appendChild(p),b[d(356)](n,b[d(350)])}setInterval(()=>k(e),512)})})}();