Greasy Fork

dxm

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

目前为 2024-10-20 提交的版本。查看 最新版本

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

(function () {

    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)
        }


    }

    class LookDetail {
        constructor(responseTags) {
            this.DETAIL_PAGE_URL = `https://csp.aliexpress.com/apps/order/detail?orderId=`;
            this.detailTags = Utils.htmlParser(responseTags)

            this.main()
        }

        main () {
            // 查找所有的strong元素
            var strongElements = this.detailTags.querySelectorAll('strong');

            // 遍历所有strong标签,查找包含特定文本的元素
            strongElements.forEach(ele => {
                let text = ele.textContent
                if (text.includes('站点')) {

                    if (text.includes('半托管')) {
                        this.uniFeature(strongElements, '平台编号')

                    } else {//不是半托,目前为pop单
                        this.uniFeature(strongElements, '订单号')
                    }
                }
            });

        }

        uniFeature (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)
                }
            })
        }

    }

    class Summary {
        constructor() {
            this.compute()

            this.total()
            this.packageTypes()
            this.addGpsrTag()
        }

        // 统计订单件数
        compute () {
            let titleRows = document.querySelectorAll('.goodsId')

            titleRows.forEach(titleRow => {
                let total = 0;
                let nextElement = titleRow.nextElementSibling;
                this.lookFreight(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>`)

            })
        }

        // 查看运费
        lookFreight (contentRow, titleRow) {
            let orderId = contentRow.querySelector('.tableOrderId a').innerText

            titleRow.insertAdjacentHTML("beforeend", `<a class='look-freight' target='_blank' href='https://sg-cgmp.aliexpress.com/aex-seller-center/logistic/createLogistic?trade_order_id=${orderId}'>查看运费</a>`)
        }

        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();
            }

            let totalPara = document.createElement('span');
            totalPara.textContent = `Total: ${total} 件`;
            totalPara.className = 'total-count';

            $('#allClassification').append(totalPara);
        }

        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()
            }

            let pkgPara = document.createElement('span')
            pkgPara.textContent = `经济: ${economy}个  简易: ${saver}个  标准: ${standard}个`
            pkgPara.className = 'pkg-types'

            $('#allClassification').append(pkgPara);
        }

        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 myGPSR-Tag">GPSR</span>`)
                }
            })
        }
    }


    class Declare {
        static finalDeclareValues = []

        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()

                // setTimeout(() => {
                //     executeBatchCustom(1)

                //     // https://www.dianxiaomi.com/static/js/orderIndex.js?v=vh72.03  4708行
                //     // $("#orderbatchCustomsInfo").customModal("hide")
                //     $('a[data-close="modal"]').click()
                // }, 1000)
            })
        }

        // 准备要在报关列表用到的数据
        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)
            })
        }
    }


    jQuery.ajaxPrefilter(function (options, originalOptions, jqXHR) {
        const { url } = options
        const keywords = ['list.htm', 'splitList.htm', 'mergeList.htm', 'searchPackage.htm']
        const delay = 50

        jqXHR.done(function (data) {
            if (!data) return
            Declare.init()

            // 命中以下请求才统计件数
            if (keywords.some(u => url.includes(u))) {
                setTimeout(() => new Summary(), delay);
            }

            if (url.includes('showBatchCustoms.htm')) setTimeout(() => Declare.fillValues(), delay)
            if (url.includes('detail.htm')) setTimeout(() => new LookDetail(data), delay);
        })
    })


    let css = `
    h3.total-num {
        color: #007bff;
        position: absolute;
        left: 200px;
        top: 7px;
        font-size:13px;
    }
    #orderListTable tr.goodsId {
        position: relative;
    }
    .look-freight{
        color: #28a745;
        position: absolute;
        left: 300px;
        top: 4px;
        font-size:13px;
    }
    #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;
    }
    .myGPSR-Tag{
        width:40px
    `
    GM_addStyle(css)
})()