// ==UserScript==
// @name 零售链山姆供应商订单页面本地化与增强
// @namespace https://retaillink.wal-mart.com/
// @version 1.7
// @description 在沃尔玛零售链山姆供应商的WebEDI订单页面上进行文本本地化,设置默认下拉选项,并格式化日期
// @author Mr.WOO
// @match *://*.retaillink2.wal-mart.com/Webedi2/*
// @grant none
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// 翻译字典
var translationDict = {
"There are no active announcements at this time.": "当前没有活动公告",
"Search returned no available pdf documents": "未找到搜索的PDF文档",
"Total Order Amount (After Adjustments)": "订单合计金额(折扣后)",
"NET 60 based on Receipt of Goods": "自收货单生效起至少60天",
"Search returned no results": "没有搜索结果",
"THIS IS A FREE GOODS ORDER": "这是一张货物免费的订单",
"Modify Search Criteria": "修改搜索条件",
"Purchase Order Number": "订单号",
"Retail Link Homepage": "零售链首页",
"Vendor Mailbox Setup": "供应商邮箱设置",
"Mailbox Maintenance": "邮箱维护",
"Prepaid (By Seller)": "预付(售货方)",
"Purchase Order Date": "订单日期",
"Total Units Ordered": "订货单位数合计",
"Additional Details": "补充的细节",
"Allowance / Charge": "补贴/收款",
"Exclude Downloaded": "排除已下载",
"Order Instructions": "说明",
"Vendor Information": "供应商信息",
"Your Requests Only": "仅限您的请求",
"Download Selected": "下载选定",
"Exception Message": "异常信息",
"F.O.B. Ship Point": "F.O.B. 装运点",
"Inbound Documents": "订单收件箱",
"PO Number & Dates": "订单号码&日期",
"Promotional Event": "促销活动",
"Item Description": "商品说明",
"Quantity Ordered": "订货数量(箱)",
"Item Instructions": "项目说明",
"Supplier Stock #": "供应商商品号",
"Total Line Items": "商品(行)合计",
"Unique Documents": "唯一文档",
"Document Number": "文档编号",
"Inbound Account": "收件箱账户",
"Supplier Number": "供应商编号",
"Partially Read": "部分已读",
"Purchase Order": "订单",
"Request Status": "请求状态",
"Vendor Country": "供应商国家",
"Announcements": "公告",
"Back to Inbox": "返回收件箱",
"Document Type": "文档类型",
"Download Date": "下载日期",
"Extended Cost": "合计成本",
"Payment Terms": "付款条件",
"PDF Dashboard": "PDF仪表板",
"Supplier Name": "供应商名称",
"Vendor Number": "供应商编号",
"Request Date": "请求日期",
"VENDOR ROUTE": "供应商路线",
"Cancel Date": "交货日期",
"Description": "说明",
"Expire Date": "过期日期",
"Export Grid": "导出表格",
"Retail Link": "零售链",
"Vendor Name": "供应商名称",
"Walmart Inc": "沃尔玛公司",
"Department": "部门",
"Free Goods": "免征税货物",
"Mailbox Id": "邮箱ID",
"Order Type": "订单类型",
"Start Time": "开始时间",
"Allowance": "补贴",
"Queue PDF": "PDF队列",
"Reporting": "报告",
"Ship Date": "起运日期",
"Complete": "完成",
"Continue": "继续",
"Currency": "货币",
"Document": "订单号",
"End Time": "结束时间",
"Handling": "人工",
"Location": "DC仓号",
"Q Search": "快速搜索",
"Sequence": "排序",
"SHENZHEN": "深圳",
"Supplier": "供应商",
"Tax Type": "税类型",
"VAT - IN": "进项税率",
"Account": "账户",
"Archive": "归档",
"Carrier": "承运人",
"Country": "国家",
"Inbound": "收件箱",
"Percent": "百分比",
"Ship To": "送货至:",
"F.O.B.": "离岸价",
"Logout": "退出",
"Search": "搜索",
"Status": "状态",
"Unread": "未读",
"Vendor": "供应商",
"Color": "箱×层",
"Total": "合计",
"Cost": "成本",
"Date": "订单日期",
"GTIN": "条码",
"Item": "商品号",
"Line": "序号",
"Pack": "罐/件",
"Read": "已读",
"Size": "罐",
"Type": "类型",
"CA\t": "箱",
"CNY": "人民币",
"UOM": "单位",
"CN": "中国",
"PO": "采购订单",
"4802": "嘉兴DC(4802)",
"4817": "成都DC(4817)",
"4819": "武汉DC(4819)",
"4873": "天津DC(4873)",
"4874": "深圳DC(4874)"
// 根据需要继续添加更多的翻译对
};
// 翻译页面中的文本内容,保留HTML标签
function translateText(text) {
let translatedText = text;
// 遍历翻译字典中的每个条目
for (let enWord in translationDict) {
// 对于数字,直接替换
if (isNaN(enWord)) {
let regex = new RegExp('\\b' + enWord + '\\b', 'g');
translatedText = translatedText.replace(regex, translationDict[enWord]);
} else {
// 对于其他文本,保持原有替换逻辑
translatedText = translatedText.split(enWord).join(translationDict[enWord]);
}
}
return translatedText;
}
function translateDOMText() {
var walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
while (node = walker.nextNode()) {
// 确保只替换每个文本节点一次
if (!node.translated) {
node.textContent = translateText(node.textContent);
node.translated = true;
}
}
}
// 观察 DOM 变动的函数
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
translateDOMText();
}
});
});
// 翻译具有特定属性的元素,例如title或alt
var elementsWithTitle = document.querySelectorAll('[type="button"], [type="submit"]');
elementsWithTitle.forEach(function(el) {
if (el.title) {
el.title = translateText(el.title);
}
});
// 翻译placeholder属性
var inputs = document.querySelectorAll('input[placeholder]');
inputs.forEach(function(input) {
var placeholderText = input.getAttribute('placeholder');
var translatedText = translationDict[placeholderText] || placeholderText;
input.setAttribute('placeholder', translatedText);
});
// 设置默认下拉选项
var selects = document.getElementsByClassName('form-control');
for (var i = 0; i < selects.length; i++) {
var select = selects[i];
switch (select.id) {
case 'docTypeInput':
select.value = '2'; // PO
break;
case 'statusInput':
select.value = 'A'; // Archive
break;
case 'vendorNumberInput':
select.value = '24980'; // Vendor Number
break;
case 'countryInput':
select.value = 'CN'; // CN
break;
// ... 其他下拉框的默认值设置
}
}
// 调整表格列宽度的函数
function adjustTableColumnWidths() {
// 获取所有的th元素
const tableHeaders = document.querySelectorAll('th[scope="col"]');
// 遍历所有的th元素
tableHeaders.forEach(header => {
// 获取现有的style.width值
const width = header.style.width;
// 检查是否存在width属性,并进行相应的调整
if (width === '50px') {
header.style.width = '60px'; // 将50px调整为60px
} else if (width === '80px') {
header.style.width = '100px'; // 将80px调整为100px
}
});
}
// 页面加载完成后执行调整列宽的操作
window.addEventListener('load', adjustTableColumnWidths);
// 如果页面已经加载完成,则立即执行调整列宽的操作
if (document.readyState === 'complete') {
adjustTableColumnWidths();
}
});
// 格式化日期的函数
const formatDate = (dateStr) => {
const date = new Date(dateStr);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${year}/${month}/${day} ${hours}:${minutes}`;
};
// 观察 DOM 变动的函数,包括data-bind和<a>标签的翻译
const observeFormatting = () => {
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
// 确保这个选择器与您的目标元素相匹配
const dateSpans = node.querySelectorAll('[data-bind="text: createdDateTime"]');
dateSpans.forEach(dateSpan => {
if (dateSpan.textContent) {
const formattedDate = formatDate(dateSpan.textContent);
dateSpan.textContent = formattedDate;
}
});
// 翻译<a>标签内的文本
const links = node.querySelectorAll('a');
links.forEach(link => {
if (link.textContent) {
link.textContent = translateText(link.textContent);
}
});
}
});
});
});
// 获取所有需要更改格式的日期元素
const dateElements = document.querySelectorAll('span[id="poDate"], span[id="shipDate"], span[id="cancelDate"]');
// 遍历所有元素,进行日期格式的转换
dateElements.forEach(element => {
// 读取原始日期字符串
let originalDate = element.textContent;
// 匹配月份和日期
const match = originalDate.match(/(\d{1,2})\/(\d{1,2})\/(\d{4})/);
if (match) {
// 重新组合日期为 yyyy/mm/dd 格式
let newDate = `${match[3]}/${match[1]}/${match[2]}`;
// 更新元素内容
element.textContent = newDate;
}
});
// 观察整个文档树,观察新增的节点
observer.observe(document.body, { childList: true, subtree: true });
};
// 页面加载完成后开始观察
window.addEventListener('load', observeFormatting);
// 如果页面已经加载完成,则立即开始观察
if (document.readyState === 'complete') {
observeFormatting();
}
// 等待页面加载完成后执行文本替换
window.addEventListener('load', function() {
translateDOMText();
observer.observe(document.body, { childList: true, subtree: true });
});
// 如果页面已经加载完成,则立即开始观察
if (document.readyState === 'complete') {
observer.observe(document.body, { childList: true, subtree: true });
}
// 创建一个按钮并设置文本和样式
const checkButton = document.createElement('button');
checkButton.textContent = '检查重复';
checkButton.className = 'mr-4 d-none d-lg-inline'; // 添加类以匹配周围的元素
checkButton.style.textDecoration = 'none'; // 移除下划线
// 检查订单号是否重复并高亮显示的函数
function checkOrderNumbers() {
// 创建一个映射,用于存储订单号和对应的DOM元素
const orderNumbers = {};
// 获取所有订单号链接
const orderNumberLinks = document.querySelectorAll('tbody tr td:nth-child(5) a');
// 遍历所有订单号链接
orderNumberLinks.forEach(link => {
// 获取订单号文本
const orderNumberText = link.textContent.trim();
// 如果映射中已有该订单号,说明发现重复
if (orderNumbers.hasOwnProperty(orderNumberText)) {
// 标记重复的订单号为红色背景和黄色文字
highlightDuplicates(orderNumbers[orderNumberText], link);
} else {
// 否则,将订单号和对应的DOM元素存储到映射中
orderNumbers[orderNumberText] = link;
}
});
}
// 标记重复订单号的函数
function highlightDuplicates(existingLink, newLink) {
// 为已存在的订单号和新发现的订单号添加样式
existingLink.style.backgroundColor = 'red';
existingLink.style.color = 'yellow';
existingLink.style.fontWeight = 'bold';
newLink.style.backgroundColor = 'red';
newLink.style.color = 'yellow';
newLink.style.fontWeight = 'bold';
}
// 将按钮插入到特定位置
const targetDiv = document.querySelector('.col-lg-8.p-0.m-0.mb-1.text-left');
if (targetDiv) {
// 在特定元素前插入按钮
const anchorTag = targetDiv.querySelector('a[data-toggle="modal"][data-target="#exportListing"]');
if (anchorTag) {
targetDiv.insertBefore(checkButton, anchorTag);
}
}
// 添加点击事件监听器
checkButton.addEventListener('click', checkOrderNumbers);
})();