wmsHelper

wms操作助手

目前為 2023-12-04 提交的版本,檢視 最新版本

// ==UserScript==
// @name         wmsHelper
// @namespace    http://tampermonkey.net/
// @version      0.2.2
// @description  wms操作助手
// @author       Ziker
// @match        https://wms.yqn.com/62100/*
// @match        https://pr-wms.yqn.com/62100/*
// @match        https://qa4-wms.yqn.com/62100/*
// @require      https://code.jquery.com/jquery-3.4.1.min.js
// @icon         https://favicon.qqsuu.cn/work.yqn.com
// @grant unsafeWindow
// @grant window.close
// @grant window.focus
// @run-at       document-body
// @noframes
// @license           AGPL License
// ==/UserScript==

window.jq = $.noConflict(true);

(function (window) {
    window.pageHelper = {
        // 等待元素可见
        async waitElementVisible(visibleTag, index, fun) {
            let node = jq(visibleTag)
            if (node === null || node[index] === null || node[index] === undefined) {
                setTimeout(() => {
                    pageHelper.waitElementVisible(visibleTag, index, fun)
                }, 500)
            } else {
                fun()
            }
        },
        sleep(duration) {
            return new Promise(resolve => {
                setTimeout(resolve, duration)
            })
        },
        showToast(msg, duration) {
            const oldNotify = document.querySelector(".custom-notify");
            if (oldNotify !== undefined && oldNotify !== null) {
                document.body.removeChild(oldNotify)
            }
            // 显示提示
            duration = isNaN(duration) ? 3000 : duration;
            const m = document.createElement('div');
            m.className = "custom-notify"
            m.innerHTML = msg;
            m.style.cssText = "display: flex;justify-content: center;align-items: center;width:60%; min-width:180px; " +
                "background:#000000; opacity:0.98; height:auto;min-height: 50px;font-size:25px; color:#fff; " +
                "line-height:30px; text-align:center; border-radius:4px; position:fixed; top:70%; left:20%; z-index:999999;";
            document.body.appendChild(m);
            setTimeout(function () {
                const d = 0.5;
                m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in';
                m.style.opacity = '0';
                setTimeout(function () {
                    if (document.body.contains(m)) {
                        document.body.removeChild(m)
                    }
                }, d * 1000);
            }, duration);
        }
    }
})(window);


(function () {
    'use strict';
    jq(document).ready(function () {
        // 顶部工具栏变化
        waitObserve("#app", () => {
            if (nonNull(document.querySelector(".forkButton"))) {
                return;
            }
            const toolbar = document.querySelector(".yqn-topbar-module");
            appendFlagNode(toolbar, "forkButton")
            const firstChildNode = toolbar.childNodes[0];
            toolbar.insertBefore(createTextButton("----万能叉车----", () => {
                getMaxForkliftCode(forkLift => {
                    if (forkLift === '') {
                        window.pageHelper.showToast("没找到叉车", 1000)
                    } else {
                        window.pageHelper.showToast(imageHtml(forkLift), 4000)
                    }
                })
            }, "ant-btn ant-btn-link perf-tracked yqn-button download-record"), firstChildNode)

            toolbar.insertBefore(createTextButton("----新容器----", () => {
                getFirstContainerNo(containerNo => {
                    if (containerNo === '') {
                        window.pageHelper.showToast("好像没容器了", 1000)
                    } else {
                        window.pageHelper.showToast(imageHtml(containerNo), 4000)
                    }
                })
            }, "ant-btn ant-btn-link perf-tracked yqn-button download-record"), firstChildNode)
        })
        // 监听 content 页面变动
        waitObserve(".yqn-base-page", () => {
            const module = document.querySelector(".yqn-header")
            if (isNull(module)) {
                return;
            }
            // 拣货单详情页面
            if (module.textContent.indexOf("拣货单") >= 0 && module.textContent.indexOf("详情") >= 0) {
                pickingOrder()
            }
            // 拣货单详情页面
            if (module.textContent.indexOf("移库单") >= 0 && module.textContent.indexOf("详情") >= 0) {
                relocationOrder()
            }
        })
    })

    // 拣货单页面
    function pickingOrder() {
        tableExecute(line => {
            const sku = line.querySelectorAll("td")[1].innerText;
            const warehouseLocation1 = line.querySelectorAll("td")[4].innerText;
            line.querySelectorAll("td")[1].appendChild(createTextButton("=>生成", () => {
                window.pageHelper.showToast(imageHtml(sku, warehouseLocation1), 7000)
            }))
        })
    }

    // 移库单页面
    function relocationOrder() {
        tableExecute(line => {
            const sku = line.querySelectorAll("td")[1].innerText;
            const warehouseLocation1 = line.querySelectorAll("td")[4].innerText;
            const warehouseLocation2 = line.querySelectorAll("td")[5].innerText;
            line.querySelectorAll("td")[1].appendChild(createTextButton("=>生成", () => {
                window.pageHelper.showToast(imageHtml(sku, warehouseLocation1, warehouseLocation2), 7000)
            }))
        })
    }

    // 表格处理
    function tableExecute(lineFun) {
        waitObserve(".ant-tabs-content.ant-tabs-content-top .ant-table-container .ant-table-tbody", () => {
            if (nonNull(document.querySelector(".customer-button-sku"))) {
                return;
            }
            appendFlagNode(document.querySelector(".yqn-header"), "customer-button-sku")
            window.pageHelper.sleep(500)
                .then(() => {
                    const tbody = document.querySelector(".ant-tabs-content.ant-tabs-content-top .ant-table-container .ant-table-tbody")
                    const lines = tbody.querySelectorAll(".ant-table-row.ant-table-row-level-0");
                    for (let i = 0; i < lines.length; i++) {
                        lineFun(lines[i])
                    }
                })
        })
    }

    // 追加标记节点
    function appendFlagNode(node, flag) {
        const divFlag = document.createElement("div");
        node.appendChild(divFlag)
        divFlag.className = flag;
        divFlag.style.display = "none"
    }

    function imageHtml() {
        let html = "<div style=\"display: flex;margin-top: 10px;margin-bottom: 10px\">";
        for (let i = 0; i < arguments.length; i++) {
            html += "    <img src=\"https://wwsix.cn/endpoint/v1/qrcode/create?code=" + arguments[i] + "&width=200&height=200&desc=1\" alt='" + arguments[i] + "'/>";
            html += "    <span style=\"width: 100px\"></span>";
        }
        html += "</div>";
        return html;
    }

    function nonNull(o) {
        return o !== null && o !== undefined;
    }

    function isNull(o) {
        return o === null || o === undefined;
    }

    // 等待出现并监听变化
    function waitObserve(visibleTag, fun, attributes = true) {
        window.pageHelper.waitElementVisible(visibleTag, 0, () => {
            new MutationObserver(function (mutationsList) {
                fun()
            }).observe(document.querySelector(visibleTag), {
                attributes: attributes,
                childList: true,
                subtree: true,
                characterData: true
            })
        })
    }

    // 创建文本按钮
    function createTextButton(name, listener, className = "ant-btn ant-btn-link perf-tracked yqn-button yqn-link-no-padding customer-button") {
        const button = document.createElement("button")
        button.type = "button"
        button.id = name
        button.className = className
        button.onclick = listener
        const span = document.createElement("span")
        span.textContent = name
        button.appendChild(span)
        return button;
    }

    // 创建按钮
    function createButton(name, listener) {
        const button = document.createElement("button")
        button.type = "button"
        button.id = name
        button.className = "ant-btn ant-btn-default perf-tracked yqn-button"
        button.onclick = listener
        const a = document.createElement("a")
        a.textContent = name
        a.className = "render-button-text"
        button.appendChild(a)
        return button;
    }

    const domain = window.location.href.indexOf("qa4") >= 0 ? 'qa4-' : window.location.href.indexOf("pr-") >= 0 ? 'pr-' : '';

    // 拿一个新容器
    function getFirstContainerNo(fuc) {
        jq.ajax({
            url: 'https://' + domain + 'gw-wms.yqn.com/api/40081/api/call/yqn_wms/bg/container/v2/list',
            method: 'POST',
            xhrFields: {
                withCredentials: true
            },
            crossDomain: true,
            contentType: 'application/json',
            data: JSON.stringify({
                "header": {
                    "xSourceAppId": "63008",
                    "guid": "6f87e073-1da1-4017-b2de-c109abcd6d123",
                    "lang": "zh",
                    "timezone": "Asia/Shanghai"
                },
                "model": {
                    "page": 1,
                    "size": 20,
                    "statusList": [
                        1
                    ],
                    "warehouseId": localStorage.getItem("warehouseId")
                }
            }),
            success: function (response) {
                if (response.code === 200 && nonNull(response.data) && nonNull(response.data.content)) {
                    if (response.data.content.length > 0) {
                        fuc(response.data.content[0].containerCode)
                    } else {
                        fuc('')
                    }
                }
            },
            error: function (xhr, status, error) {
                console.log('Request failed:', error);
            }
        });
    }

    // 拿一个全能叉车
    function getMaxForkliftCode(fuc) {
        jq.ajax({
            url: 'https://' + domain + 'gw-wms.yqn.com/api/40081/api/call/yqn_wms/bg/forklift/v2/list',
            method: 'POST',
            xhrFields: {
                withCredentials: true
            },
            crossDomain: true,
            contentType: 'application/json',
            data: JSON.stringify({
                "header": {
                    "xSourceAppId": "63008",
                    "guid": "6f87e073-1da1-4017-b2de-c109abcd6d123",
                    "lang": "zh",
                    "timezone": "Asia/Shanghai"
                },
                "model": {
                    "page": 1,
                    "size": 100,
                    "warehouseId": localStorage.getItem("warehouseId")
                }
            }),
            success: function (response) {
                if (response.code === 200 && nonNull(response.data) && nonNull(response.data.content) && response.data.content.length > 0) {
                    let emptyCode = ''
                    let code = ''
                    let areMaxLayer = 0
                    let areMaxLen = 0
                    let emptyAreMaxLayer = 0;
                    for (let i = 0; i < response.data.content.length; i++) {
                        const forklift = response.data.content[i];
                        const num = isNull(forklift.maximumLayer) ? 0 : forklift.maximumLayer;
                        // 空库区
                        if (isNull(forklift.warehouseAreaList) || forklift.warehouseAreaList.length === 0) {
                            if (emptyAreMaxLayer <= num) {
                                emptyAreMaxLayer = num;
                                emptyCode = forklift.code;
                            }
                        } else {
                            // 非空库区
                            if (areMaxLen <= forklift.warehouseAreaList.length && areMaxLayer <= num) {
                                areMaxLen = forklift.warehouseAreaList.length;
                                areMaxLayer = num;
                                code = forklift.code;
                            }
                        }
                    }
                    fuc(emptyCode.length !== 0 ? emptyCode : code)
                }
            },
            error: function (xhr, status, error) {
                console.log('Request failed:', error);
            }
        });
    }
})();