dxm

统计当前订单件数 & 针对区域定价的报关金额进行批量填充

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         dxm
// @namespace    https://greasyfork.org/zh-CN/scripts/462551
// @version      2.64
// @author       Huang
// @description  统计当前订单件数 & 针对区域定价的报关金额进行批量填充
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=dianxiaomi.com
// @match        https://www.dianxiaomi.com/order/*
// @grant        GM_addStyle
// @run-at       document-start
// ==/UserScript==

(t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const o=document.createElement("style");o.textContent=t,document.head.append(o)})(" h3.total-num{color:#007bff;position:absolute;left:200px;top:7px;font-size:13px}#orderListTable tr.goodsId{position:relative}.operation-btns{position:absolute;left:300px;top:4px}.operation-btns a{color:#28a745;font-size:13px;margin-right:20px}#dxmOrderDetailDiv{display:none}.total-count{color:red;line-height:30px;font-size:13px;margin-left:10px}.pkg-types{color:gray;line-height:30px;font-size:13px;margin-left:10px} ");

(function () {
  'use strict';

  var __defProp = Object.defineProperty;
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
  class Utils {
    // 模拟input
    static tEvent(b, a) {
      if (b) {
        window.newhtmlevents = window.newhtmlevents || document.createEvent("HTMLEvents");
        newhtmlevents.initEvent(a, true, true);
        return b.dispatchEvent(newhtmlevents);
      }
    }
    static simulateInput(ele, val) {
      this.tEvent(ele, "click");
      this.tEvent(ele, "input");
      ele.value = val;
      this.tEvent(ele, "keyup");
      this.tEvent(ele, "change");
      this.tEvent(ele, "blur");
    }
    static htmlParser(htmlString) {
      let parser = new DOMParser();
      let doc = parser.parseFromString(htmlString, "text/html");
      return doc;
    }
    static isGpsrCountry(countryCode) {
      const countries = ["奥地利", "比利时", "保加利亚", "塞浦路斯", "克罗地亚", "捷克共和国", "丹麦", "爱沙尼亚", "芬兰", "法国", "德国", "希腊", "匈牙利", "爱尔兰", "意大利", "拉脱维亚", "立陶宛", "卢森堡", "马耳他", "荷兰", "波兰", "葡萄牙", "罗马尼亚", "斯洛伐克", "斯洛文尼亚", "西班牙", "瑞典"];
      return countries.includes(countryCode);
    }
    /**
     * 从URL中提取指定键的查询参数值。
     * @param {string} url - 包含查询参数的URL。
     * @param {string} key - 要提取值的查询参数键。
     * @returns {string|null} - 指定键的查询参数值,如果不存在则返回null。
     */
    static getUrlKeyValuePairs(url, key) {
      const pairs = {};
      const parts = url.split("?")[1].split("&");
      for (const part of parts) {
        const [key2, value] = part.split("=");
        pairs[key2] = value;
      }
      return pairs[key] || null;
    }
    static isiPad() {
      const ua = navigator.userAgent;
      const platform = navigator.platform;
      if (/iPad/i.test(ua) || platform === "iPad") {
        return true;
      }
      return platform === "MacIntel" && navigator.maxTouchPoints > 1;
    }
  }
  const _Declare = class _Declare {
    static init() {
      $(document).off("click", `a[onclick="showBatchCustoms();"]`);
      $(document).on("click", `a[onclick="showBatchCustoms();"]`, () => {
        _Declare.prepareData();
      });
      _Declare.applyTrackingDirect();
    }
    static applyTrackingDirect() {
      $(`button[onclick="batchMoveProcessed();"]`).each(function() {
        $(this).attr("onclick", null);
      });
      $(document).off("click", "[id^='moveProcessBtn']");
      $(document).on("click", "[id^='moveProcessBtn']", () => {
        let isCheckedAnyone = $(`#showSelCheckboxNum`).length > 0;
        if (!isCheckedAnyone) {
          $.fn.message({ type: "error", msg: "请至少选择一个订单ya" });
          return;
        }
        _Declare.prepareData();
        showBatchCustoms();
      });
    }
    // 准备要在报关列表用到的数据
    static prepareData() {
      let t = [], that = this, _reg = /[^0-9.]/g;
      $(`input[name='packageId']`).each(function() {
        if ($(this).prop("checked")) {
          let common = $(this).closest("tr").next().children();
          const isJIT = $(this).closest("tr").next()[0].getAttribute("data-platform").includes("Choice");
          if (!isJIT) {
            let eleList = common.eq(0).find("tr");
            let rightPrice = common.eq(1).text().replace(_reg, "");
            rightPrice = Number(rightPrice);
            let singleItem = eleList.length == 1;
            if (singleItem) {
              let leftPrice = eleList.find("p:contains('USD')").text().replace(_reg, "");
              leftPrice = Number(leftPrice);
              let finalPrice = leftPrice < rightPrice ? leftPrice : rightPrice;
              t.push(finalPrice);
            } else {
              eleList.each((i, e) => t.push($(e).find("p:contains('USD')").text().replace(_reg, "")));
            }
          }
          that.finalDeclareValues = t;
        }
      });
    }
    static fillValues() {
      let that = this;
      const [chsName, engName, weight] = ["狗衣服", "Dog Clothes", 50];
      $(`input[name="declaredValues"]`).each(function(index) {
        Utils.simulateInput($(this).get(0), that.finalDeclareValues[index]);
      });
      $(`input[name="nameChs"]`).each(function(index) {
        if ($(this).val() == "") Utils.simulateInput($(this).get(0), chsName);
      });
      $(`input[name="nameEns"]`).each(function(index) {
        if ($(this).val() == "") Utils.simulateInput($(this).get(0), engName);
      });
      $(`input[name="weights"]`).each(function(index) {
        let curVal = $(this).val();
        if (curVal == "" || curVal == 0) Utils.simulateInput($(this).get(0), weight);
      });
    }
  };
  __publicField(_Declare, "finalDeclareValues", []);
  let Declare = _Declare;
  class Summary {
    constructor(url) {
      this.curURL = url;
      if (Utils.isiPad() === false) {
        this.compute();
      }
      this.total();
      this.packageTypes();
      this.addGpsrTag();
    }
    /**
     * 判断当前url是否可以追踪物流信息。
     * @returns {boolean} - 如果可以追踪物流信息,则返回true,否则返回false。
     */
    ifCanTrack() {
      let ifTargetURL = this.curURL.includes("list.htm");
      if (ifTargetURL) {
        let state = Utils.getUrlKeyValuePairs(this.curURL, "state");
        if (state === "shipped") {
          return true;
        }
        return false;
      }
      return false;
    }
    // 统计订单件数
    compute() {
      let titleRows = document.querySelectorAll(".goodsId");
      titleRows.forEach((titleRow) => {
        let total = 0;
        let nextElement = titleRow.nextElementSibling;
        this.addFreightAndTrackElements(nextElement, titleRow);
        while (nextElement && !nextElement.classList.contains("goodsId")) {
          let numBoxes = nextElement.querySelectorAll('[class^="circularSpan"]');
          for (let numBox of numBoxes) {
            let num = parseInt(numBox.textContent);
            total += num;
          }
          nextElement = nextElement.nextElementSibling;
        }
        titleRow.insertAdjacentHTML("beforeend", `<h3 class='total-num'>${total}件</h3>`);
      });
    }
    addFreightAndTrackElements(contentRow, titleRow, total) {
      const baseURL = `https://csp.aliexpress.com/m_apps`;
      const operationDiv = $('<div class="operation-btns"></div>');
      let orderId = contentRow.querySelector(".tableOrderId a").innerText;
      const freightLink = $(`<a target='_blank' href='${baseURL}/logistic/create_ship_cn?trade_order_id=${orderId}'>查看运费</a>`);
      operationDiv.append(freightLink);
      let ifCanTrack = this.ifCanTrack();
      if (ifCanTrack) {
        const logisticsLink = $(`<a target='_blank' href='${baseURL}/logistics/tracking?tradeOrderId=${orderId}'>物流轨迹</a>`);
        operationDiv.append(logisticsLink);
      }
      $(titleRow).append(operationDiv);
    }
    total() {
      let total = 0;
      let pieceSpans = document.querySelector("#orderListTable").querySelectorAll('[class^="circularSpan"]');
      if (pieceSpans.length == 0) return;
      pieceSpans.forEach((pieceSpan) => {
        let num = parseInt(pieceSpan.textContent);
        total += num;
      });
      let existingTotal = document.querySelector(".total-count");
      if (existingTotal) {
        existingTotal.remove();
      }
      $("#allClassification").append(`<span class="total-count">Total: ${total} 件</span>`);
    }
    packageTypes() {
      let pkgs = document.querySelectorAll(".buyerSelectProvider");
      if (pkgs.length == 0) return;
      let economy = 0, saver = 0, standard = 0;
      pkgs.forEach((pkg) => {
        if (pkg.textContent.includes("Economy")) {
          economy++;
        } else if (pkg.textContent.includes("Saver")) {
          saver++;
        } else if (pkg.textContent.includes("Standard")) {
          standard++;
        }
      });
      let existingTotal = document.querySelector(".pkg-types");
      if (existingTotal) {
        existingTotal.remove();
      }
      $("#allClassification").append(`<span class="pkg-types">经济: ${economy}个  简易: ${saver}个  标准: ${standard}个</span>`);
    }
    addGpsrTag() {
      let titleRows = document.querySelectorAll(".goodsId");
      titleRows.forEach((titleRow) => {
        let nextElement = titleRow.nextElementSibling;
        let tag = $(nextElement).find('a[onclick^="dxmOrderDetail("]').next();
        let country = tag.closest("td").prev().children().last().text().replace(/「|」/g, "");
        let isGSPR = Utils.isGpsrCountry(country);
        if (isGSPR) {
          tag.append(`<span class="squareSpanOra">G</span>`);
        }
      });
    }
  }
  class LookDetail {
    constructor(responseTags) {
      this.DETAIL_PAGE_URL = `https://csp.aliexpress.com/apps/order/detail?orderId=`;
      this.detailTags = Utils.htmlParser(responseTags);
      this.main();
    }
    main() {
      var strongElements = this.detailTags.querySelectorAll("strong");
      strongElements.forEach((ele) => {
        let text = ele.textContent;
        if (text.includes("站点")) {
          if (text.includes("半托管")) {
            this.jump2AliOrderDetail(strongElements, "平台编号");
          } else {
            this.jump2AliOrderDetail(strongElements, "订单号");
          }
        }
      });
    }
    jump2AliOrderDetail(strongElements, splitText) {
      strongElements.forEach((viceEle) => {
        let orderNumTag = viceEle.textContent;
        if (orderNumTag.includes(splitText)) {
          let orderId = orderNumTag.split(splitText)[1].replace(":", "");
          let url = `${this.DETAIL_PAGE_URL}${orderId}`;
          $("#orderDetailClose1").click();
          window.open(url);
        }
      });
    }
  }
  const originalOpen = XMLHttpRequest.prototype.open;
  const originalSend = XMLHttpRequest.prototype.send;
  XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
    this._requestUrl = url;
    return originalOpen.apply(this, arguments);
  };
  XMLHttpRequest.prototype.send = function(body) {
    const handleResponse = () => {
      if (this.readyState === 4 && this.status >= 200 && this.status < 300) {
        const { _requestUrl: url, responseText: data } = this;
        if (!data) return;
        Declare.init();
        const delay = 50;
        const keywords = ["list.htm", "splitList.htm", "mergeList.htm", "searchPackage.htm"];
        if (keywords.some((u) => url.includes(u))) setTimeout(() => new Summary(url), delay);
        if (url.includes("showBatchCustoms.htm")) setTimeout(() => Declare.fillValues(), delay);
        if (url.includes("detail.htm")) setTimeout(() => new LookDetail(data), delay);
      }
    };
    this.addEventListener("readystatechange", handleResponse);
    return originalSend.apply(this, arguments);
  };

})();