Greasy Fork 还支持 简体中文。

Price Helper

複製 Vendoritem ID / 商品連結;貼上 ID + 受託人(找不到受託人則僅貼 ID);清空搜尋欄。

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Price Helper
// @namespace    AOScript
// @version      1.0
// @description  複製 Vendoritem ID / 商品連結;貼上 ID + 受託人(找不到受託人則僅貼 ID);清空搜尋欄。
// @author       AO-AO
// @match        https://price.tw.coupang.com/*
// @grant        none
// @license      MIT
// @run-at       document-idle
// ==/UserScript==

(function () {
  'use strict';

  /** ================================
   *  🔧 顯示/隱藏開關(true=顯示 / false=隱藏)
   *  ================================ */
  const ENABLE_VENDOR_ID          = true;  // 📋 複製 Vendoritem ID
  const ENABLE_ALL_LINKS          = false;  // 📋 複製所有商品連結(去重)
  const ENABLE_PASTE_ID_ASSIGNEE  = true;  // 📎 貼上 ID + 受託人(找不到受託人就只貼 ID)
  const ENABLE_CLEAR_INPUT        = true;  // 🧹 清空搜尋欄

  /** ================================
   *  📏 位置控制(可調)
   *  ================================ */
  const TOP_START = 50;     // 第一顆按鈕起始高度(再往下挪)
  const ROW_GAP   = 50;     // 同組內按鈕縱向間距
  const GROUP_GAP = 70;     // 上下兩組按鈕之間的大間距

  // --- 上組(兩顆) ---
  const top1 = TOP_START;                  // 第一顆
  const top2 = TOP_START + ROW_GAP;        // 第二顆
  // --- 下組(兩顆) ---
  const top3 = TOP_START + ROW_GAP + GROUP_GAP;             // 第三顆
  const top4 = TOP_START + ROW_GAP + GROUP_GAP + ROW_GAP;   // 第四顆

  /** ================================
   *  🎨 顯目配色
   *  ================================ */
  const palette = {
    vendorId: '#FF6B00',   // 橙色:Vendor ID
    allLinks: '#0078FF',   // 藍色:所有連結
    pasteIA:  '#00A651',   // 綠色:貼 ID + 受託人
    clearBox: '#E53935'    // 紅色:清空
  };

  // ✅ 模擬原生輸入,觸發框架監聽(AntD / React)
  function setNativeValue(element, value) {
    const prototype = Object.getPrototypeOf(element);
    const valueSetter = Object.getOwnPropertyDescriptor(prototype, 'value')?.set;
    if (valueSetter) valueSetter.call(element, value);
    else element.value = value;
    element.dispatchEvent(new Event('input', { bubbles: true }));
    element.dispatchEvent(new Event('change', { bubbles: true }));
  }

  // ✅ 嘗試觸發搜尋(優先按搜尋按鈕,否則送 Enter)
  function triggerSearch(inputEl) {
    const searchBtn =
      document.querySelector('button[data-elm-id="Button__Search"]') ||
      document.querySelector('button[data-elm-id*="Search"]') ||
      document.querySelector('button[aria-label*="search" i]');
    if (searchBtn) {
      searchBtn.click();
      return;
    }
    if (inputEl) {
      const opts = { bubbles: true, cancelable: true, key: 'Enter', code: 'Enter', keyCode: 13, which: 13 };
      inputEl.dispatchEvent(new KeyboardEvent('keydown', opts));
      inputEl.dispatchEvent(new KeyboardEvent('keypress', opts));
      inputEl.dispatchEvent(new KeyboardEvent('keyup', opts));
    }
  }

  // ✅ 通用按鈕建立(極簡樣式,字體跟隨頁面)
  function createButton(text, top, bgColor, onClick) {
    const btn = document.createElement('button');
    btn.textContent = text;
    btn.style.position = 'fixed';
    btn.style.top = `${top}px`;
    btn.style.right = '20px';
    btn.style.zIndex = '99999';
    btn.style.padding = '9px 11px';
    btn.style.backgroundColor = bgColor;
    btn.style.color = '#fff';
    btn.style.border = 'none';
    btn.style.borderRadius = '6px';
    btn.style.cursor = 'pointer';

    // 字體跟隨頁面原本大小(不固定 13px)
    const bodyFontSize = getComputedStyle(document.body)?.fontSize;
    if (bodyFontSize && bodyFontSize !== '0px') {
      btn.style.fontSize = bodyFontSize; // 例如 14px / 15px / 16px
    } // 否則不設置,讓瀏覽器自行繼承

    // 字型採用系統字體,與頁面相容
    btn.style.fontFamily = 'inherit';

    btn.addEventListener('click', (e) => onClick(e, btn));
    document.body.appendChild(btn);
  }

  // 🔎 取得 Vendoritem ID(取第一筆)
  function getVendorItemId() {
    const vendorDivs = Array.from(document.querySelectorAll('div[data-elm-id="text"]'))
      .filter((el) => el.textContent.trim() === 'Vendoritem ID')
      .map((el) => el.parentElement);
    if (vendorDivs.length === 0) return null;
    const vendorText = vendorDivs[0].textContent.replace('Vendoritem ID', '').trim();
    return vendorText || null;
  }

  // 🔎 取得受託人(顯示為「受託人 : 名字」)
  function getAssigneeName() {
    const assigneeSpan = document.querySelector('[data-elm-id="TaskAssigneeName"]');
    if (!assigneeSpan) return null;
    const m = assigneeSpan.textContent.match(/受託人\s*:\s*(\S+)/);
    return m && m[1] ? m[1].trim() : null;
  }

  const INPUT_SELECTOR = 'input[data-elm-id="Input__SearchFilter"]';

  // 1) 📋 複製 Vendoritem ID(可隱藏)
  if (ENABLE_VENDOR_ID) {
    createButton('📋 複製 Vendoritem ID', top1, palette.vendorId, (_e, btn) => {
      const id = getVendorItemId();
      if (!id) {
        alert('找不到 Vendoritem ID');
        return;
      }
      GM_setClipboard(id);
      btn.textContent = '✅ 已複製 ID';
      setTimeout(() => (btn.textContent = '📋 複製 Vendoritem ID'), 1500);
    });
  }

  // 2) 📋 複製所有商品連結(去重)(可隱藏)
  if (ENABLE_ALL_LINKS) {
    createButton('📋 複製所有連結', top2, palette.allLinks, (_e, btn) => {
      const links = document.querySelectorAll('a.ManualMappingListContainer__siteLink___hZYay');
      const hrefs = Array.from(links).map((link) => link.href).filter(Boolean);
      const uniqueHrefs = Array.from(new Set(hrefs));
      GM_setClipboard(uniqueHrefs.join('\n'));
      btn.textContent = `✅ 已複製 ${uniqueHrefs.length} 筆`;
      setTimeout(() => (btn.textContent = '📋 複製所有連結'), 1500);
    });
  }

  // 3) 📎 貼上 ID + 受託人(找不到受託人就只貼 ID)(可隱藏)
  if (ENABLE_PASTE_ID_ASSIGNEE) {
    createButton('📎 貼上 ID + 受託人', top3, palette.pasteIA, (_e, btn) => {
      const inputBox = document.querySelector(INPUT_SELECTOR);
      const id = getVendorItemId();
      const assignee = getAssigneeName();
      if (!inputBox || !id) {
        alert('找不到輸入框或 Vendoritem ID');
        return;
      }
      const combined = assignee ? `${id};${assignee}` : id;
      setNativeValue(inputBox, combined);
      triggerSearch(inputBox);
      btn.textContent = assignee ? '✅ 已貼上 ID + 受託人' : '✅ 已貼上 ID';
      setTimeout(() => (btn.textContent = '📎 貼上 ID + 受託人'), 1500);
    });
  }

  // 4) 🧹 清空搜尋欄(可隱藏)
  if (ENABLE_CLEAR_INPUT) {
    createButton('🧹 清空搜尋欄', top4, palette.clearBox, (_e, btn) => {
      const inputBox = document.querySelector(INPUT_SELECTOR);
      if (!inputBox) {
        alert('找不到輸入框');
        return;
      }
      setNativeValue(inputBox, '');
      triggerSearch(inputBox);
      btn.textContent = '✅ 已清空';
      setTimeout(() => (btn.textContent = '🧹 清空搜尋欄'), 1500);
    });
  }
})();
``