From 54341f0a0b9474a69c8d19a7acee4813478cfd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Wed, 18 Mar 2026 10:32:15 +0800 Subject: [PATCH] 1 --- mv2_simple_crx/src/actions/amazon.js | 126 +++++++++++++++++++++++++ mv2_simple_crx/src/background/index.js | 8 +- mv2_simple_crx/src/ui/index.html | 1 + 3 files changed, 134 insertions(+), 1 deletion(-) diff --git a/mv2_simple_crx/src/actions/amazon.js b/mv2_simple_crx/src/actions/amazon.js index 64dadd5..64db60c 100644 --- a/mv2_simple_crx/src/actions/amazon.js +++ b/mv2_simple_crx/src/actions/amazon.js @@ -32,6 +32,58 @@ export function injected_amazon_homepage_search(params) { return { ok: false, error: 'no_submit' }; } +/** 语言设置页:在 customer-preferences/edit 页面选择语言并点击 Save Changes + * 入参使用短码:EN / ES / AR / DE / HE / KO / PT / ZH_CN / ZH_TW + */ +export function injected_amazon_switch_language(params) { + const mapping = { + EN: 'en_US', + ES: 'es_US', + AR: 'ar_AE', + DE: 'de_DE', + HE: 'he_IL', + KO: 'ko_KR', + PT: 'pt_BR', + ZH_CN: 'zh_CN', + ZH_TW: 'zh_TW', + }; + const raw = params && params.lang != null ? String(params.lang).trim().toUpperCase() : 'ZH_CN'; + const code = Object.prototype.hasOwnProperty.call(mapping, raw) ? raw : 'ZH_CN'; + const switch_lang = mapping[code]; + const href_sel = `a[href="#switch-lang=${switch_lang}"]`; + const deadline = Date.now() + 6000; + let link = null; + while (Date.now() < deadline) { + link = document.querySelector(href_sel); + if (link) { + const r = link.getBoundingClientRect(); + if (r.width > 0 && r.height > 0) break; + } + const t0 = performance.now(); + while (performance.now() - t0 < 40) {} + } + if (!link) return { ok: false, error: 'lang_option_timeout', lang: code }; + link.click(); + + // 尝试点击「保存修改」按钮 + const save_deadline = Date.now() + 6000; + let save = null; + while (Date.now() < save_deadline) { + save = + document.querySelector('input[type="submit"][value*="Save"]') || + document.querySelector('input[type="submit"][aria-labelledby*="icp-save-button"]') || + document.querySelector('span.icp-save-button input[type="submit"]'); + if (save) break; + const t1 = performance.now(); + while (performance.now() - t1 < 40) {} + } + if (save) { + save.click(); + } + + return { ok: true, lang: code }; +} + export function injected_amazon_search_list(params) { const start_url = params && params.url ? String(params.url) : location.href; const category_keyword = params && params.category_keyword ? String(params.category_keyword).trim() : ''; @@ -499,6 +551,80 @@ amazon_search_list.params = { limit: { type: 'number', desc: '抓取数量上限(默认 100,最大 200)', default: 100 }, }; +const AMAZON_HOME_FOR_LANG = + 'https://www.amazon.com/customer-preferences/edit?ie=UTF8&preferencesReturnUrl=%2F&ref_=topnav_lang_ais&language=zh_CN¤cy=HKD'; + +export function amazon_set_language(data, sendResponse) { + const mapping = { + EN: 'en_US', + ES: 'es_US', + AR: 'ar_AE', + DE: 'de_DE', + HE: 'he_IL', + KO: 'ko_KR', + PT: 'pt_BR', + ZH_CN: 'zh_CN', + ZH_TW: 'zh_TW', + }; + const raw_lang = data && data.lang != null ? String(data.lang).trim().toUpperCase() : 'ZH_CN'; + const code = Object.prototype.hasOwnProperty.call(mapping, raw_lang) ? raw_lang : 'ZH_CN'; + const send_action = (action, payload) => { + if (typeof sendResponse === 'function') { + sendResponse({ action, data: payload }); + sendResponse.log && sendResponse.log(payload); + } + }; + return new Promise(async (resolve, reject) => { + const tab_task = create_tab_task(AMAZON_HOME_FOR_LANG) + .set_latest(false) + .set_bounds({ top: 20, left: 20, width: 1280, height: 900 }); + try { + const tab = await tab_task.open_async(); + await wait_tab_complete(tab.id); + const raw = await tab.execute_script(injected_amazon_switch_language, [{ lang: code }], 'document_idle'); + const inj = Array.isArray(raw) ? raw[0] : raw; + if (!inj || !inj.ok) { + throw new Error((inj && inj.error) || 'switch_language_failed'); + } + await wait_tab_complete(tab.id); + const final_url = await new Promise((res, rej) => { + chrome.tabs.get(tab.id, (t) => { + if (chrome.runtime.lastError) return rej(new Error(chrome.runtime.lastError.message)); + res(t && t.url ? t.url : ''); + }); + }); + const result = { + code: 0, + status: true, + message: 'ok', + data: { tab_id: tab.id, lang: inj.lang, url: final_url }, + }; + send_action('amazon_set_language', result); + resolve({ tab_id: tab.id, lang: inj.lang, url: final_url }); + tab.remove(0); + } catch (err) { + send_action('amazon_set_language', { + code: 30, + status: false, + message: (err && err.message) || String(err), + data: null, + documentURI: AMAZON_HOME_FOR_LANG, + }); + reject(err); + } + }); +} + +amazon_set_language.desc = + 'Amazon 顶栏语言:打开美站首页,悬停语言区后点击列表项(#switch-lang),切换购物界面语言'; +amazon_set_language.params = { + lang: { + type: 'string', + desc: 'EN / ES / AR / DE / HE / KO / PT / ZH_CN(默认) / ZH_TW', + default: 'ZH_CN', + }, +}; + // ---------- 后台:商品详情 / 评论 ---------- function normalize_product_url(u) { diff --git a/mv2_simple_crx/src/background/index.js b/mv2_simple_crx/src/background/index.js index 212e316..b8b3d06 100644 --- a/mv2_simple_crx/src/background/index.js +++ b/mv2_simple_crx/src/background/index.js @@ -1,8 +1,14 @@ -import { amazon_search_list, amazon_product_detail, amazon_product_reviews } from '../actions/amazon.js'; +import { + amazon_search_list, + amazon_set_language, + amazon_product_detail, + amazon_product_reviews, +} from '../actions/amazon.js'; const actions = { amazon_search_list, + amazon_set_language, amazon_product_detail, amazon_product_reviews, }; diff --git a/mv2_simple_crx/src/ui/index.html b/mv2_simple_crx/src/ui/index.html index ede6de4..05158bb 100644 --- a/mv2_simple_crx/src/ui/index.html +++ b/mv2_simple_crx/src/ui/index.html @@ -25,6 +25,7 @@ +