以下适用物润船联的网货平台系统

1.网页指定元素内,鼠标右键菜单选项并填入指定元素事件

// ==UserScript==
// @name         快速审核插件
// @namespace    http://*
// @version      1.0
// @description  try to take over the world!
// @author       Jagyl
// @match        https://admin.jagyl.top/*
// @icon         https://*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 预定义的文本内容,包括二级菜单项
    const predefinedMenu = [
        {
            text: '证件缺失  >>',
            subItems: ['  上传身份证!','  上传车辆协议,没协议用身份证人像正面!', '  上传电子版道路运输证!', '  上传对应驾驶证证和副本!', '  上传对应行驶证和副本!', '  上传道路运输证!','  上传从业资格证','  上传人车合照,要求人站车前,车头车牌全部拍到!', '  上传最新的车辆年检记录!']
        },
        {
            text: '证件质量 >>',
            subItems: ['  身份证模糊!', '  驾驶证模糊!','  行驶证模糊!','  从业资格证模糊!','  道路运输证模糊!']
        },
        {
            text: ' 证件逾期 >>',
            subItems:  ['  身份证逾期!', '  驾驶证逾期!','  行驶证年检逾期!','  从业资格证逾期!','  道路运输证逾期!']
        },
        {
            text: 'A------     >>',
            subItems: ['A-1', 'A-2', 'A-3']
        },
        {
            text: 'B------     >>',
            subItems: ['B-1', 'B-2', 'B-3']
        }
    ];

    // 监听右键点击事件
    document.addEventListener('contextmenu', function(e) {
        // 找到目标 textarea
        let textareaElement = e.target.closest('textarea.ivu-input');

        // 检查是否点击在指定的 textarea 上
        if (textareaElement) {
            e.preventDefault(); // 阻止默认右键菜单

            // 移除已存在的自定义菜单,避免重复
            removeExistingMenu();

            // 显示自定义菜单
            showCustomMenu(e.pageX, e.pageY, textareaElement);
        }
    });

    // 显示自定义菜单并提供预定义的主菜单和子菜单
    function showCustomMenu(x, y, textareaElement) {
        let customMenu = document.createElement('div');
        customMenu.id = 'customMenu';  // 给菜单一个ID,方便删除
        customMenu.style.position = 'absolute';
        customMenu.style.backgroundColor = 'white';
        customMenu.style.padding = '5px';
        customMenu.style.border = '1px solid #ccc';
        customMenu.style.zIndex = '10000';
        customMenu.style.whiteSpace = 'nowrap';  // 避免文本换行
        customMenu.style.minWidth = '100px';  // 设置最小宽度
        customMenu.style.maxWidth = '300px';  // 限制最大宽度,防止过长文本撑开页面
        customMenu.style.boxShadow = '0px 0px 10px rgba(0, 0, 0, 0.1)'; // 添加阴影以美化

        // 动态调整菜单位置,防止超出屏幕
        document.body.appendChild(customMenu); // 先添加到body中,再调整位置
        adjustMenuPosition(customMenu, x, y);

        // 创建主菜单项
        predefinedMenu.forEach(function(menuItem) {
            let mainMenuItem = document.createElement('div');
            mainMenuItem.textContent = menuItem.text;
            mainMenuItem.style.padding = '5px';
            mainMenuItem.style.cursor = 'pointer';
            mainMenuItem.style.position = 'relative';

            // 创建子菜单容器
            let subMenu = document.createElement('div');
            subMenu.style.position = 'absolute';
            subMenu.style.left = '100%';
            subMenu.style.top = '0';
            subMenu.style.backgroundColor = 'white';
            subMenu.style.padding = '5px';
            subMenu.style.border = '1px solid #ccc';
            subMenu.style.whiteSpace = 'nowrap';  // 避免文本换行
            subMenu.style.minWidth = '100px';  // 设置最小宽度
            subMenu.style.maxWidth = '300px';  // 限制最大宽度
            subMenu.style.display = 'none';  // 初始时隐藏
            subMenu.style.zIndex = '10001';
            subMenu.style.boxShadow = '0px 0px 10px rgba(0, 0, 0, 0.1)'; // 添加阴影

            // 为每个主菜单项创建对应的子菜单项
            menuItem.subItems.forEach(function(subItemText) {
                let subMenuItem = document.createElement('div');
                subMenuItem.textContent = subItemText;
                subMenuItem.style.padding = '5px';
                subMenuItem.style.cursor = 'pointer';

                // 当点击子菜单时,将其内容追加到 textarea
                subMenuItem.onclick = function() {
                    // 在现有内容后追加文本
                    textareaElement.value += subItemText;
                    removeExistingMenu(); // 填充后隐藏菜单
                };
                subMenu.appendChild(subMenuItem);
            });

            // 鼠标悬停时显示子菜单
            mainMenuItem.addEventListener('mouseover', function() {
                subMenu.style.display = 'block';
            });

            // 鼠标移出时隐藏子菜单
            mainMenuItem.addEventListener('mouseout', function() {
                subMenu.style.display = 'none';
            });

            mainMenuItem.appendChild(subMenu);
            customMenu.appendChild(mainMenuItem);
        });

        // 点击其他地方时移除菜单
        document.addEventListener('click', function removeMenu(event) {
            if (!customMenu.contains(event.target)) {
                removeExistingMenu();
                document.removeEventListener('click', removeMenu);
            }
        });
    }

    // 调整菜单位置,防止被浏览器窗口遮挡,左下角为基准弹出
    function adjustMenuPosition(menu, x, y) {
        // 获取窗口的宽度和高度
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;

        // 获取菜单的尺寸
        const menuRect = menu.getBoundingClientRect();

        // 如果菜单超出右边界,则向左调整
        if ((x + menuRect.width) > windowWidth) {
            menu.style.left = `${x - menuRect.width}px`;
        } else {
            menu.style.left = `${x}px`;
        }

        // 菜单左下角对齐:如果菜单超出底部,则向上调整
        if ((y + menuRect.height) > windowHeight) {
            menu.style.top = `${y - menuRect.height}px`;
        } else {
            menu.style.top = `${y - menuRect.height}px`;  // 左下角对齐鼠标位置
        }
    }

    // 移除现有的自定义菜单(如果有)
    function removeExistingMenu() {
        let existingMenu = document.getElementById('customMenu');
        if (existingMenu) {
            document.body.removeChild(existingMenu);
        }
    }

})();

2.其他表单内的自动化:

// ==UserScript==
// @name         车辆审核综合插件2
// @namespace    http://*
// @version      1.2
// @description  提供多种便捷操作,如更改textarea高度、同步年检日期、同步车辆所有人信息以及复制VIN码和车牌号到剪贴板。
// @author       Jagyl
// @match        https://admin.jagyl.top/*
// @icon         https://*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Function to change the height of textarea elements
    function changeTextareaHeight() {
        const textareas = document.querySelectorAll('textarea');
        textareas.forEach(textarea => {
            textarea.style.height = '200px';
        });
    }

    // Function to copy and update the date
    function copyAndUpdateDate() {
        const currentDate = new Date();
        const nextYear = (currentDate.getFullYear() + 1).toString();

        const sourceXPath = "//label[contains(text(), '车辆行驶证注册日期')]/..//input";
        const sourceNode = document.evaluate(sourceXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        if (sourceNode) {
            let sourceText = sourceNode.value;
            const updatedText = sourceText.replace(/(\d{4})/, nextYear);

            const targetXPath = "//label[contains(text(), '行驶证到期日期')]/..//input";
            const targetNode = document.evaluate(targetXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

            if (targetNode) {
                targetNode.value = updatedText;
            } else {
                console.error('Target <input> element not found.');
            }
        } else {
            console.error('Source <input> element not found.');
        }
    }

    // Function to copy vehicle owner information
    function copyVehicleOwnerInfo() {
        const sourceXPath = "//label[contains(text(), '车辆所有人')]/..//input";
        const sourceNode = document.evaluate(sourceXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        if (sourceNode) {
            const sourceText = sourceNode.value;

            const targetXPath = "//label[contains(text(), '业户名称')]/..//input";
            const targetNode = document.evaluate(targetXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

            if (targetNode) {
                targetNode.value = sourceText;
            } else {
                console.error('Target <input> element for vehicle owner not found.');
            }
        } else {
            console.error('Source <input> element for vehicle owner not found.');
        }
    }

    // Function to copy VIN and another value to clipboard
    function copyVINAndAnotherValueToClipboard() {
        const vinXPath = "//label[contains(text(), '道路运输证字号')]/..//input";
        const vinNode = document.evaluate(vinXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        const anotherValueXPath = "//label[contains(text(), '车牌号')]/..//input";
        const anotherValueNode = document.evaluate(anotherValueXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        if (vinNode && anotherValueNode) {
            const valuesList = [vinNode.value, anotherValueNode.value].join('\n');

            navigator.clipboard.writeText(valuesList)
                .then(() => {
                    alert('VIN码和车牌号已复制到剪切板');
                })
                .catch(err => {
                    console.error('获取失败: ', err);
                });
        } else {
            console.error('识别码异常');
        }
    }

    // Function to fill input from clipboard
    async function fillInputFromClipboard() {
        try {
            const clipText = await navigator.clipboard.readText();
            const xpathExpression = "//label[contains(text(), '道路运输证到期日期')]/..//input"; // 修改为实际的XPath
            const targetNode = document.evaluate(xpathExpression, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

            if (targetNode) {
                targetNode.value = clipText.trim();
                alert('从剪贴板填充输入成功!');
            } else {
                console.error('目标 <input> 元素未找到。');
                alert('目标 <input> 元素未找到。');
            }
        } catch (err) {
            console.error('无法从剪贴板读取数据: ', err);
            alert('无法从剪贴板读取数据,请检查权限设置。');
        }
    }

    // 创建第一个按钮元素 - 更改textarea高度
    const button1 = createButton('审核意见插件', 10, 10, changeTextareaHeight);

    // 创建第二个按钮元素 - 复制并更新日期
    const button2 = createButton('同步年检日期', 110, 10, copyAndUpdateDate);

    // 创建第三个按钮元素 - 同步车辆所有人
    const button3 = createButton('同步业户名称', 10, 55, copyVehicleOwnerInfo);

    // 创建第四个按钮元素 - 复制VIN码和车牌号
    const button4 = createButton('<运输证>车牌', 110, 55, copyVINAndAnotherValueToClipboard);

    // 创建第五个按钮元素 - 从剪贴板填充输入
    const button5 = createButton('运输证有效期', 10, 100, fillInputFromClipboard);

    // 将五个按钮添加到文档中
    [button1, button2, button3, button4, button5].forEach(button => document.body.appendChild(button));

    // Helper function to create a button
    function createButton(text, left, bottom, clickHandler) {
        const button = document.createElement('button');
        button.textContent = text;
        button.style.position = 'fixed';
        button.style.bottom = `${bottom}px`;
        button.style.padding = '9px';
        button.style.left = `${left}px`;
        button.style.zIndex = '1000';
        button.addEventListener('click', clickHandler);
        return button;
    }
})();

交通部网页查询

// ==UserScript==
// @name         交通运输部运输证信息插件
// @namespace    http://tampermonkey.net/
// @version      2024-09-28
// @description  运输证查询信息插件
// @author       JAGYL
// @match        https://ysfw.mot.gov.cn/NetRoadCGSS-web/information/query?searchType=owner
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Function to read clipboard and fill input elements
    function fillInputsFromClipboard() {
        navigator.clipboard.readText()
            .then(clipText => {
                const values = clipText.split('\n').map(value => value.trim());
                if (values.length === 2) {
                    const [vin, anotherValue] = values;
                    const vehicleNoNode = document.evaluate("//*[@id='transCertificateCode']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                    const transCertificateCodeNode = document.evaluate("//*[@name='vehicleNo']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

                    if (vehicleNoNode && transCertificateCodeNode) {
                        vehicleNoNode.value = vin;
                        transCertificateCodeNode.value = anotherValue;
                        alert('输入框已成功填充!');
                    } else {
                        console.error('One or both of the <input> elements not found.');
                    }
                } else {
                    console.error('Clipboard does not contain exactly two values.');
                }
            })
            .catch(err => {
                console.error('Failed to read from clipboard: ', err);
            });
    }

    // Function to get information from a specific location using XPath and copy to clipboard
    async function getInfoAndCopyToClipboard() {
        const xpathExpression = "//*[@id='search-2']/table[2]/tbody/tr[3]/td[4]";
        const result = document.evaluate(xpathExpression, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        if (result) {
            try {
                await navigator.clipboard.writeText(result.innerText);
                alert('指定位置的信息已复制到剪贴板: ' + result.innerText);
            } catch (err) {
                console.error('Failed to write to clipboard: ', err);
                alert('无法将信息复制到剪贴板,请检查权限设置。');
            }
        } else {
            console.error('无法找到指定位置的元素。');
            alert('无法找到指定位置的元素。');
        }
    }

    // 创建第一个按钮 - 从剪贴板填充输入
    const buttonFill = document.createElement('button');
    buttonFill.textContent = '运输证车号';
    buttonFill.style.position = 'fixed';
    buttonFill.style.bottom = '10px';
    buttonFill.style.padding = '10px';
    buttonFill.style.left = '10px';
    buttonFill.style.zIndex = '1000';
    buttonFill.addEventListener('click', fillInputsFromClipboard);

    // 创建第二个按钮 - 获取指定位置的信息并复制到剪贴板
    const buttonGetInfo = document.createElement('button');
    buttonGetInfo.textContent = '获取日期';
    buttonGetInfo.style.position = 'fixed';
    buttonGetInfo.style.bottom = '10px';
    buttonGetInfo.style.padding = '10px';
    buttonGetInfo.style.left = '140px'; // 放置在第一个按钮旁边
    buttonGetInfo.style.zIndex = '1000';
    buttonGetInfo.addEventListener('click', getInfoAndCopyToClipboard);

    // 将两个按钮添加到文档中
    document.body.appendChild(buttonFill);
    document.body.appendChild(buttonGetInfo);
})();