SKU批量填充

淘宝、拼多多SKU批量填充

// ==UserScript==
// @name         SKU批量填充
// @namespace    none
// @version      0.1.4
// @description  淘宝、拼多多SKU批量填充
// @author       鹿秋夏
// @include      https://sell.publish.tmall.com/tmall/publish.htm?*
// @include      https://mms.pinduoduo.com/goods/goods_add/index?*
// @grant        none
// ==/UserScript==

(() => {
  "use strict";

  // 检查当前页面是否为目标页面
  const isTaobaoPage = window.location.href.includes(
    "https://sell.publish.tmall.com/tmall/publish.htm?"
  );
  const isPinduoduoPage = window.location.href.includes(
    "https://mms.pinduoduo.com/goods/goods_add/index?"
  );

  if (!isTaobaoPage && !isPinduoduoPage) return;

  // 等待指定元素加载完毕后执行回调函数
  const waitForElement = (selector, callback, isXPath = false) => {
    let targetElement;
    if (isXPath) {
      targetElement = document.evaluate(
        selector,
        document,
        null,
        XPathResult.FIRST_ORDERED_NODE_TYPE,
        null
      ).singleNodeValue;
    } else {
      targetElement = document.querySelector(selector);
    }
    if (targetElement) {
      callback(targetElement);
    } else {
      setTimeout(() => waitForElement(selector, callback, isXPath), 100); // 等待0.1秒后重新尝试获取
    }
  };

  // 添加自定义按钮
  const addCustomButton = (targetElement, isPinduoduo) => {
    const customButton = document.createElement("button");
    customButton.id = "custom-button";
    customButton.textContent = "批量SKU填充";
    customButton.style.borderRadius = "3px"; // 圆角
    customButton.style.width = "100px"; // 宽度
    customButton.style.height = "32px"; // 高度
    customButton.style.backgroundColor = "rgb(234, 244, 253)"; // 背景颜色
    customButton.style.color = "rgb(76, 148, 253)"; // 字体颜色
    customButton.style.outline = "none"; // 去除焦点样式
    customButton.style.border = "1px solid rgb(69, 143, 236)"; // 边框样式
    customButton.style.boxShadow = "none"; // 去除阴影样式
    customButton.style.position = "absolute"; // 设置为绝对定位
    customButton.style.cursor = "auto"; // 默认鼠标指针样式
    customButton.style.lineHeight = isPinduoduo ? "0px" : "32px";

    // 动态计算左边距
    const targetRect = targetElement.getBoundingClientRect();
    customButton.style.left = `${
      targetRect.left + targetRect.width + (isPinduoduo ? -497 : 12)
    }px`; // 在目标元素右边12px处或右边-497px处

    // 按钮点击事件处理
    customButton.addEventListener("click", async () => {
      try {
        const text = await navigator.clipboard.readText();
        // 对剪贴板内容进行分割与过滤操作,得到处理后的列表
        const processedList = text
          .split("\n")
          .filter((item) => item.trim() !== "");

        // 循环处理列表中的每个元素
        for (const [index, value] of processedList.entries()) {
          setTimeout(() => {
            if (isTaobaoPage) {
              const addButton = document.evaluate(
                '//div[@id="struct-p-1627207"]//button[contains(@class, "add")]',
                document,
                null,
                XPathResult.FIRST_ORDERED_NODE_TYPE,
                null
              ).singleNodeValue;
              addButton.click();
            }

            // 等待输入框加载完毕
            const inputSelector = isTaobaoPage
              ? 'input[placeholder="主色(必选)"][value=""]'
              : '//div[text()="款式"]/following::input[@placeholder="请输入规格名称" and @value=""]';
            waitForElement(
              inputSelector,
              (inputElement) => {
                inputElement.value = value;
                inputElement.dispatchEvent(
                  new Event("input", { bubbles: true, cancelable: true })
                );
                inputElement.focus();
                inputElement.blur();
                const clickEvent = new MouseEvent("click", {
                  bubbles: true,
                  cancelable: true,
                  view: window,
                });
                inputElement.dispatchEvent(clickEvent);

                // 等待指定时间后检查输入框是否存在
                setTimeout(() => {
                  const checkInput = isTaobaoPage
                    ? document.querySelector(inputSelector)
                    : document.evaluate(
                        inputSelector,
                        document,
                        null,
                        XPathResult.FIRST_ORDERED_NODE_TYPE,
                        null
                      ).singleNodeValue;
                  if (!checkInput) {
                    // 如果输入框不存在,清空内容并重新输入
                    inputElement.value = "";
                    inputElement.dispatchEvent(
                      new Event("input", { bubbles: true, cancelable: true })
                    );
                    inputElement.focus();
                    inputElement.value = value;
                    inputElement.dispatchEvent(
                      new Event("input", { bubbles: true, cancelable: true })
                    );
                    inputElement.focus();
                    inputElement.blur();
                  }
                }, 100);
              },
              isPinduoduo
            );
          }, index * (isTaobaoPage ? 100 : 700)); // 每个元素间隔100ms或500ms处理
        }
      } catch (error) {
        console.error(error);
      }
    });

    // 鼠标悬停时修改鼠标指针和样式
    customButton.addEventListener("mouseenter", () => {
      customButton.style.cursor = "pointer";
      customButton.style.backgroundColor = "rgb(204, 214, 223)"; // 悬停时的背景颜色
    });

    // 鼠标离开时恢复原样式
    customButton.addEventListener("mouseleave", () => {
      customButton.style.cursor = "auto";
      customButton.style.backgroundColor = "rgb(234, 244, 253)";
    });

    // 将按钮插入到目标元素的父节点中
    targetElement.parentNode.insertBefore(
      customButton,
      targetElement.nextSibling
    );
  };

  // 每隔500ms检测页面是否加载了按钮
  const checkButtonInterval = setInterval(() => {
    const customButton = document.getElementById("custom-button");
    if (!customButton) {
      // 等待目标元素加载完毕后添加按钮
      if (isTaobaoPage) {
        waitForElement("div[class='front']", (targetElement) =>
          addCustomButton(targetElement, false)
        );
      } else if (isPinduoduoPage) {
        waitForElement(
          '//div[.//div[text()="款式"] and @class="goods-spec-row-left"]',
          (targetElement) => addCustomButton(targetElement, true),
          true
        );
      }
    } else {
      // 清除所有重复的按钮,只保留一个
      const buttons = document.querySelectorAll("#custom-button");
      if (buttons.length > 1) {
        buttons.forEach((button, index) => index > 0 && button.remove());
      }
    }
  }, 500);
})();