// ==UserScript==
// @name link工具
// @namespace http://tampermonkey.net/
// @version 0.7.4
// @description 点击复制,提取链接
// @author lwj
// @match *://m.linkmcn.com/*
// @match *://detail.tmall.com/item*
// @match *://item.taobao.com/item*
// @match *://chaoshi.detail.tmall.com/item*
// @match *://traveldetail.fliggy.com/item*
// @match *://detail.tmall.hk/hk/item*
// @license MIT
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_setClipboard
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function () {
// 版本号
var versionTitleTxt = 'Version 0.7.4';
// 检查当前页面 URL 是否匹配指定的网址
var isHomeURL = function () {
var currentURL = window.location.href;
return currentURL.indexOf("https://m.linkmcn.com/#/live/plan?select=") !== -1;
};
// 从 localStorage 中获取上一次的 URL,如果没有则设置为空字符串
let lastCurrentURL = localStorage.getItem('lastCurrentURL') || '';
var isTableCardURL = function () {
return window.location.href.indexOf("https://m.linkmcn.com/#/live/plan/tableCard/") !== -1;
};
var isBatchPrintURL = function () {
return window.location.href.indexOf("https://m.linkmcn.com/#/live/plan/batchPrint") !== -1;
};
var isTmallItemURL = function () {
var url = window.location.href;
// 检查URL是否包含任何指定的域名或路径
return (
url.indexOf("https://detail.tmall.com/item") !== -1 ||
url.indexOf("https://detail.tmall.hk/hk/item") !== -1 ||
url.indexOf("https://item.taobao.com/item") !== -1 ||
url.indexOf("https://chaoshi.detail.tmall.com/item") !== -1 ||
url.indexOf("https://traveldetail.fliggy.com/item") !== -1
);
}
var notificationTimer; // 通知计时器
var isHiding = false; // 标志,表示是否正在隐藏通知
let countSort_notificationTimeout = null;// 排序提示定时器
let temp_itemId = '';
class ToggleButtonComponent {
constructor(localStorageKey, buttonText, dropdownContainer, useSpecialSwitch = 0, defaultState = false) {
this.localStorageKey = localStorageKey;
this.switchState = localStorage.getItem(this.localStorageKey) === null ? defaultState : localStorage.getItem(this.localStorageKey) === 'true';
this.buttonText = buttonText;
this.dropdownContainer = dropdownContainer;
this.useSpecialSwitch = useSpecialSwitch === 1;
this.createComponent();
}
createComponent() {
// 创建按钮容器
this.buttonContainer = document.createElement('div');
this.buttonContainer.classList.add('flex', 'items-center', 'dropdown-item');
this.buttonContainer.style.cssText = 'padding: 12px 16px; user-select: none; cursor: pointer; display: flex; justify-content: space-between; align-items: center;';
// 创建按钮文本
this.buttonTextElement = document.createElement('span');
this.buttonTextElement.textContent = this.buttonText;
this.buttonTextElement.classList.add('lh-22');
this.buttonContainer.appendChild(this.buttonTextElement);
if (this.useSpecialSwitch) {
// 创建特殊开关样式按钮
this.createSpecialSwitch();
} else {
// 创建普通按钮
this.createStandardButton();
}
// 将按钮容器添加到下拉容器中
this.dropdownContainer.appendChild(this.buttonContainer);
// 创建对应的空的子页面并设置样式
this.secondaryContent = document.createElement('div');
this.secondaryContent.id = this.localStorageKey + '-secondary-content';
this.secondaryContent.style.cssText = 'margin: 0px 10px; display: none; padding: 10px 12px; background: #E9E9E9; border: 1px solid #D2D2D2; border-radius: 10px;';
// 将子页面添加到按钮容器的下方
this.dropdownContainer.appendChild(this.secondaryContent);
}
createStandardButton() {
this.button = document.createElement('button');
this.button.id = 'main_standardFunShowButton';
this.button.style.cssText = 'background: none; border: none; font-size: 16px; cursor: pointer; transition: transform 0.3s; margin: 0px 6px';
this.button.appendChild(createSVGIcon());
this.buttonContainer.appendChild(this.button);
// 绑定点击事件
this.button.addEventListener('click', () => this.handleStandardButtonClick());
// 给标题绑定模拟点击开关事件
this.buttonTextElement.addEventListener('click', () => this.titleToSwitchClick());
}
handleStandardButtonClick() {
// 切换二级页面显示状态
const secondaryContent = document.getElementById(this.localStorageKey + '-secondary-content');
if (secondaryContent) {
secondaryContent.style.display = secondaryContent.style.display === 'block' ? 'none' : 'block';
} else {
console.log(`${this.buttonText} 二级页面异常`);
}
// 旋转按钮图标
const icon = this.button.querySelector('svg');
const rotation = icon.style.transform === 'rotate(90deg)' ? 'rotate(0deg)' : 'rotate(90deg)';
icon.style.transform = rotation;
}
createSpecialSwitch() {
this.button = document.createElement('button');
this.button.innerHTML = '<div class="ant-switch-handle"></div><span class="ant-switch-inner"><span class="ant-switch-inner-checked"></span><span class="ant-switch-inner-unchecked"></span></span>';
this.button.setAttribute('type', 'button');
this.button.setAttribute('role', 'switch');
this.button.setAttribute('aria-checked', this.switchState); // 设置开关状态
this.button.classList.add('ant-switch', 'css-9fw9up');
if (this.switchState) {
this.button.classList.add('ant-switch-checked');
}
this.buttonContainer.appendChild(this.button);
// 添加点击事件监听
this.button.addEventListener('click', () => this.handleSwitchClick());
}
handleSwitchClick() {
// 切换开关状态
const newState = this.button.getAttribute('aria-checked') === 'true' ? 'false' : 'true';
this.button.setAttribute('aria-checked', newState);
if (newState === 'true') {
this.button.classList.add('ant-switch-checked');
showNotification(`${this.buttonText}:开启`);
} else {
this.button.classList.remove('ant-switch-checked');
showNotification(`${this.buttonText}:关闭`);
}
// 更新开关状态
updateSwitchState(this.localStorageKey, newState === 'true');
}
titleToSwitchClick() {
// 模拟点击开关按钮
this.button.click();
}
remove_titleToSwitchClick() {
// 移除模拟点击开关按钮
this.buttonTextElement.removeEventListener('click', () => this.titleToSwitchClick());
}
// 获取开关状态
getSwitchState() {
return this.button.getAttribute('aria-checked') === 'true';
}
// 获取子页面元素
getSecondaryContent() {
return this.secondaryContent;
}
}
class SonToggleButtonComponent extends ToggleButtonComponent {
constructor(localStorageKey, buttonText, dropdownContainer, descriptionText, useSpecialSwitch = false, defaultState = false) {
super(localStorageKey, buttonText, dropdownContainer, useSpecialSwitch, defaultState);
this.buttonText = buttonText;
this.descriptionText = descriptionText;
this.createAdditionalContent();
}
// 创建附加内容容器
createAdditionalContent() {
// 修改按钮文本样式并去除 class="lh-22"
this.buttonTextElement.style.cssText = 'font-size: 14px; margin: 0;';
this.buttonTextElement.classList.remove('lh-22');
// 调整父类的内容容器样式
this.buttonContainer.style.cssText = 'display: flex;user-select: none; justify-content: space-between; align-items: center; padding: 0;';
// 新增的说明容器
this.descriptionContainer = document.createElement('div');
this.descriptionContainer.classList.add('description-content');
this.descriptionContainer.style.cssText = 'font-size: 12px; color: #9B9B9B; user-select: none; margin: 5px 0px; padding-bottom: 5px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #D2D2D2; white-space: pre-wrap;';
this.descriptionContainer.textContent = this.descriptionText;
// 子设置容器
this.childSettingsContainer = document.createElement('div');
this.childSettingsContainer.classList.add('child-settings');
this.childSettingsContainer.style.cssText = 'display: block; justify-content: space-between; align-items: center;';
// 初始化子开关容器的样式
this.updateSwitchStyle();
// 将说明容器和子设置容器添加到下拉容器中
this.dropdownContainer.appendChild(this.buttonContainer);
this.dropdownContainer.appendChild(this.descriptionContainer);
this.dropdownContainer.appendChild(this.childSettingsContainer);
}
// 重写createSpecialSwitch以添加额外的类
createSpecialSwitch() {
// 确保父类方法被正确调用
super.createSpecialSwitch();
// 确保 this.button 已初始化
if (!this.button) {
console.error('this.button is not initialized');
return;
}
// 将函数定义为对象的方法
this.autoInput_handleSwitchClick = () => {
if (!this.getSwitchState()) {
itemSort_inputConter.showSwitchDiv(true); // 显示输入内容选择框
itemSort_countInputFun.showNumberControlDiv(false); // 隐藏数字控制区
itemSort_countInputFun.toggleDivButtonState(false); // 关闭数字控制按钮
}
};
if (this.buttonText === '自动填充') {
// console.log(this.buttonText);
this.button.addEventListener('click', () => this.autoInput_handleSwitchClick());
}
// 添加额外的类
this.button.classList.add('ant-switch-small');
}
// 独立的方法用于更新开关样式
updateSwitchStyle() {
if (!this.getSwitchState()) {
initializeContainerStyle(this.childSettingsContainer, false); // 使用函数初始化
}
}
// 控制单独组件的开启关闭
showSwitchDiv(flag) {
if (flag) {
initializeContainerStyle(this.buttonContainer, true);
initializeContainerStyle(this.descriptionContainer, true);
} else {
initializeContainerStyle(this.buttonContainer, false);
initializeContainerStyle(this.descriptionContainer, false);
}
}
createSelectBox(options = ['', '0', '1', '2', '3', '999'], savedKey = this.localStorageKey + '_savedValue', container = this.buttonContainer) {
// 先移除button元素
if (this.button) {
this.buttonContainer.removeChild(this.button);
}
// 创建下拉框
const selectBox = document.createElement('select');
selectBox.setAttribute('id', this.localStorageKey + '-select-box');
selectBox.style.cssText = `
font-size: 14px;
margin: 0;
width: 42px;
height: 18px;
border: 1px solid rgb(155, 155, 155);
background-color: rgb(249,249,249);
color: rgb(155, 155, 155);
border-radius: 20px;
padding: 0 2.5%;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: relative;
cursor: pointer;
`;
options.forEach(value => {
const option = document.createElement('option');
option.value = value;
option.style.cssText = `
text-align: center;
padding: 0 5px;
`;
option.textContent = value === '' ? '空' : value;
selectBox.appendChild(option);
});
const savedValue = localStorage.getItem(savedKey) || options[1];
selectBox.value = savedValue;
selectBox.addEventListener('change', () => {
localStorage.setItem(savedKey, selectBox.value);
updateSwitchState(this.localStorageKey, selectBox.value);
// 悬浮时和激活时边框颜色变化
selectBox.style.borderColor = '#ff6200';
});
// 悬浮时和激活时边框颜色变化
selectBox.addEventListener('mouseover', function () {
selectBox.style.borderColor = '#ff6200';
});
selectBox.addEventListener('mouseout', function () {
if (!selectBox.matches(':focus')) {
selectBox.style.borderColor = 'rgb(155, 155, 155)';
}
});
selectBox.addEventListener('focus', function () {
selectBox.style.borderColor = '#ff6200';
});
selectBox.addEventListener('blur', function () {
selectBox.style.borderColor = 'rgb(155, 155, 155)';
});
container.appendChild(selectBox);
}
createDivButton(beforeText, afterText, onClickCallback = null, container = this.buttonContainer) {
// 先移除button元素
if (this.button) {
this.buttonContainer.removeChild(this.button);
}
this.beforeText = beforeText;
this.afterText = afterText;
this.onClickCallback = onClickCallback;
// 功能开启按钮
this.divButton = document.createElement('div');
this.divButton.setAttribute('id', this.localStorageKey + '_divButton');
this.divButton.textContent = beforeText;
this.divButton.style.cssText = `
font-size: 14px;
margin: 0;
width: 42px;
height: 18px;
border: 1px solid rgb(155, 155, 155);
background-color: rgb(249,249,249);
color: rgb(155, 155, 155);
border-radius: 20px;
padding: 0 2%;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: relative;
cursor: pointer;
user-select: none;
text-align: center;
`;
// 悬浮时和激活时边框颜色变化
this.divButton.addEventListener('mouseover', () => {
if (this.divButton.textContent === beforeText) {
this.divButton.style.borderColor = '#ff6200';
}
else {
this.divButton.style.borderColor = 'rgb(155, 155, 155)';
}
});
this.divButton.addEventListener('mouseout', () => {
if (this.divButton.textContent === beforeText) {
this.divButton.style.borderColor = 'rgb(155, 155, 155)';
}
else {
this.divButton.style.borderColor = 'rgb(249, 249, 249)';
}
});
// 按钮点击事件
this.divButton.addEventListener('click', () => {
this.toggleDivButtonState();
});
container.appendChild(this.divButton);
}
// 控制单独组件的开启关闭
toggleDivButtonState(isActivated = null) {
// 如果提供了isActivated参数,则根据参数设置状态,否则根据当前状态切换
const shouldActivate = isActivated !== null ? isActivated : (this.divButton.textContent === this.beforeText);
if (shouldActivate) {
this.divButton.textContent = this.afterText;
this.divButton.style.color = '#fff';
this.divButton.style.backgroundColor = '#ff0000';
this.divButton.style.borderColor = '#fff';
showNotification(`${this.buttonText}:开启`);
if (this.onClickCallback) {
this.onClickCallback(true);
}
} else {
this.divButton.textContent = this.beforeText;
this.divButton.style.color = 'rgb(155, 155, 155)';
this.divButton.style.backgroundColor = 'rgb(249,249,249)';
this.divButton.style.borderColor = 'rgb(155, 155, 155)';
showNotification(`${this.buttonText}:关闭`);
if (this.onClickCallback) {
this.onClickCallback(false);
}
}
}
// 判断开关开启状态
getDivButtonState() {
if (this.divButton.textContent === this.beforeText) {
return false;// 开关开启状态
} else {
return true;// 开关关闭状态
}
}
createNumberControDiv(defaultNumber = 0, single = false, countType = 'none', savedKey = this.localStorageKey + '_savedValue', container = this.buttonContainer) {
if (single) {
//先移除button元素
if (this.button) {
this.buttonContainer.removeChild(this.button);
}
}
// 数字文本及SVG控制区
this.numberControDiv = document.createElement('div');
this.numberControDiv.style.cssText = `
font-size: 14px;
display: flex;
align-items: center;
min-width: 42px;
height: 18px;
width: auto;
border: 1px solid rgb(155, 155, 155);
background-color: rgb(249,249,249);
color: rgb(155, 155, 155);
border-radius: 20px;
padding: 0 2.5%;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: relative;
cursor: default;
`;
// 数字文本
this.countText = document.createElement('span');
this.countText.textContent = defaultNumber; // 使用默认数字
this.countText.style.cssText = 'font-size: 14px; margin: 0 auto;';
this.numberControDiv.appendChild(this.countText);
// 创建函数来设置悬停颜色
function addHoverEffect(svgElement) {
svgElement.addEventListener('mouseover', function () {
var path = svgElement.querySelector('path');
if (path) {
path.setAttribute('data-original-fill', path.getAttribute('fill'));
path.setAttribute('fill', '#ff6200');
}
});
svgElement.addEventListener('mouseout', function () {
var path = svgElement.querySelector('path');
if (path) {
path.setAttribute('fill', path.getAttribute('data-original-fill'));
}
});
}
// SVG控制区
var svgControlDiv = document.createElement('div');
svgControlDiv.style.cssText = 'display: flex; flex-direction: column; justify-content: space-between; cursor: pointer;';
// 上方SVG
var svgUp = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgUp.setAttribute("width", "6");
svgUp.setAttribute("height", "6");
svgUp.setAttribute("viewBox", "0 0 1024 1024");
svgUp.innerHTML = `
<path d="M854.016 739.328l-313.344-309.248-313.344 309.248q-14.336 14.336-32.768 21.504t-37.376 7.168-36.864-7.168-32.256-21.504q-29.696-28.672-29.696-68.608t29.696-68.608l376.832-373.76q14.336-14.336 34.304-22.528t40.448-9.216 39.424 5.12 31.232 20.48l382.976 379.904q28.672 28.672 28.672 68.608t-28.672 68.608q-14.336 14.336-32.768 21.504t-37.376 7.168-36.864-7.168-32.256-21.504z" fill="#8a8a8a"></path>
`;
addHoverEffect(svgUp);
svgControlDiv.appendChild(svgUp);
// 下方SVG
var svgDown = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgDown.setAttribute("width", "6");
svgDown.setAttribute("height", "6");
svgDown.setAttribute("viewBox", "0 0 1024 1024");
svgDown.innerHTML = `
<path d="M857.088 224.256q28.672-28.672 69.12-28.672t69.12 28.672q29.696 28.672 29.696 68.608t-29.696 68.608l-382.976 380.928q-12.288 14.336-30.72 19.968t-38.912 4.608-40.448-8.704-34.304-22.016l-376.832-374.784q-29.696-28.672-29.696-68.608t29.696-68.608q14.336-14.336 32.256-21.504t36.864-7.168 37.376 7.168 32.768 21.504l313.344 309.248z" fill="#8a8a8a"></path>
`;
addHoverEffect(svgDown);
svgControlDiv.appendChild(svgDown);
svgUp.addEventListener('click', () => this.updateCount(1, 'countInput'));
svgDown.addEventListener('click', () => this.updateCount(-1, 'countInput'));
this.numberControDiv.appendChild(svgControlDiv);
container.appendChild(this.numberControDiv);
}
// 用于更新数字文本的方法
updateCount(increment, notificationType) {
let currentValue = parseInt(this.countText.textContent);
currentValue += increment;
this.setCount(currentValue);
if (notificationType === 'countInput') {
if (this.getCount() > 0) {
showNotification(`下一个输入序号:${currentValue}`, 0);
} else {
this.setCount(1);
showNotification('当前已是最小序号', 1500);
this.countSort_reShowNotification();
}
}
}
// 获取当前的计数
getCount() {
return this.countText.textContent;
}
// 设置当前计数
setCount(count) {
this.countText.textContent = count;
}
// 控制numberControDiv显示/隐藏的方法
showNumberControlDiv(visible) {
if (this.numberControDiv) {
this.numberControDiv.style.display = visible ? 'flex' : 'none';
}
}
// 常显通知方法
countSort_reShowNotification() {
var show_time = 1500;
if (countSort_notificationTimeout) {
clearTimeout(countSort_notificationTimeout);
}
countSort_notificationTimeout = setTimeout(() => {
if (this.getDivButtonState()) {
showNotification("下一个输入序号:" + this.getCount(), 0);
}
countSort_notificationTimeout = null;
}, show_time); // 延迟后触发
}
// 重写handleSwitchClick以控制子页面的可点击性
handleSwitchClick() {
super.handleSwitchClick();
const newState = this.getSwitchState();
initializeContainerStyle(this.childSettingsContainer, newState);
}
// 获取子设置容器
getChildSettingsContainer() {
return this.childSettingsContainer;
}
getSelectBoxValue() {
const selectBox = this.buttonContainer.querySelector('select');
return selectBox ? selectBox.value : null;
}
}
// 创建开关容器元素
var switchesContainer = document.createElement('div');
switchesContainer.classList.add('flex', 'items-center', 'justify-between', 'pb-12');
switchesContainer.style.cssText = 'position: fixed; top: 0px; left: 50%; transform: translateX(-50%); z-index: 9999;';
if (isHomeURL()) {
document.body.appendChild(switchesContainer);
}
// 封装函数返回SVG图标
function createSVGIcon() {
var svgIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgIcon.setAttribute('class', 'icon custom-svg'); // 添加自定义类名
svgIcon.setAttribute('viewBox', '0 0 1024 1024');
svgIcon.setAttribute('width', '20');
svgIcon.setAttribute('height', '20');
svgIcon.setAttribute('fill', '#bbbbbb');
svgIcon.innerHTML = '<path d="M288.791335 65.582671l446.41733 446.417329-446.41733 446.417329z"></path>';
svgIcon.style.cssText = 'vertical-align: middle;'; // 垂直居中样式
return svgIcon;
}
// 添加事件监听用于下拉箭头
document.addEventListener('mouseenter', function (event) {
if (event.target instanceof Element && event.target.matches('svg.icon.custom-svg')) { // 仅匹配具有自定义类名的SVG
event.target.setAttribute('fill', '#ff6200');
}
}, true);
document.addEventListener('mouseleave', function (event) {
if (event.target instanceof Element && event.target.matches('svg.icon.custom-svg')) { // 仅匹配具有自定义类名的SVG
event.target.setAttribute('fill', '#bbbbbb');
}
}, true);
var dropdown_style = document.createElement('style');
dropdown_style.textContent = `
@keyframes dropdownContentAnimation {
0% {
transform: translateX(-50%) translateY(14px) scale(0);
}
100% {
transform: translateX(-50%) translateY(0) scale(1);
}
}
@keyframes dropdownContentExitAnimation {
0% {
transform: translateX(-50%) translateY(0) scale(1);
}
100% {
transform: translateX(-50%) translateY(14px) scale(0);
}
}
#dropdownContent.show {
animation: dropdownContentAnimation 0.3s ease-out;
}
#dropdownContent.hide {
animation: dropdownContentExitAnimation 0.3s ease-out;
}
@keyframes dropdownButtonAnimation {
0% { transform: scale(1); }
35% { transform: scale(1.15, 1.3); }
85% { transform: scale(0.94); }
100% { transform: scale(1); }
}
#dropdownButtonAnimate.animate {
animation: dropdownButtonAnimation 0.45s ease-out;
}
`;
document.head.appendChild(dropdown_style);
var dropdownContainer = document.createElement('div');
dropdownContainer.style.cssText = 'position: relative; display: inline-block;';
var dropdownButton = document.createElement('button');
dropdownButton.id = 'dropdownButtonAnimate'; // 添加 id 以便于应用动画
dropdownButton.textContent = '更多功能';
dropdownButton.style.cssText = 'margin-top: 0px; padding: 0px 10px; cursor: pointer; border-radius: 999px;z-index: 2;';
dropdownButton.classList.add('ant-btn', 'css-9fw9up', 'ant-btn-default', 'primaryButton___N3z1x');
var dropdownDeck = document.createElement('div');
dropdownDeck.style.cssText = `
top: 0;
left: 0;
width: 200px;
height: 60px;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
`;
var dropdownContent = document.createElement('div');
dropdownContent.id = 'dropdownContent';
dropdownContent.style.cssText = `
display: none;
position: absolute;
background-color: #f9f9f9;
top: 0px;
left: 50%;
transform: translateX(-50%);
min-width: 200px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
border-radius: 16px;
max-height: 360px;
overflow-y: auto; /* 使用 auto 可以根据内容是否溢出显示滚动条 */
scrollbar-width: none; /* 隐藏滚动条,适用于 Firefox */
-ms-overflow-style: none; /* 隐藏滚动条,适用于 IE 和 Edge */
transform-origin: top center;
`;
var dropdownMask = document.createElement('div');
dropdownMask.style.cssText = `
position: sticky;
top: 0;
left: 0;
width: 200px;
height: 46px;
backdrop-filter: none;
border-radius: 10px 10px 0 0;
box-sizing: border-box;
border-bottom: 0px solid #DDD;
z-index: 99; /* 确保遮罩在内容上方 */
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(249, 249, 249, 0);
`;
dropdownDeck.appendChild(dropdownButton);
dropdownContainer.appendChild(dropdownDeck);
dropdownContent.appendChild(dropdownMask);
dropdownContainer.appendChild(dropdownContent);
switchesContainer.appendChild(dropdownContainer);
function on_dropdownMask() {
dropdownMask.style.borderBottom = '1px solid #DDD';
dropdownMask.style.backdropFilter = 'blur(8px) brightness(90%)';
dropdownMask.style.backgroundColor = 'rgba(249, 249, 249, 0.5)';
dropdownMask.style.height = '60px';
}
function off_dropdownMask() {
dropdownMask.style.borderBottom = '0px solid #DDD';
dropdownMask.style.backdropFilter = 'none';
dropdownMask.style.backgroundColor = 'rgba(249, 249, 249, 0)';
dropdownMask.style.height = '46px';
}
dropdownButton.addEventListener('click', function () {
// 强制重新开始动画
this.classList.remove('animate');
// 使用 requestAnimationFrame 确保动画类已被移除
requestAnimationFrame(() => {
this.classList.add('animate');
});
this.addEventListener('animationend', function () {
this.classList.remove('animate');
}, { once: true });
if (dropdownContent.style.display === 'none' || dropdownContent.classList.contains('hide')) {
dropdownContent.style.display = 'block';
dropdownContent.classList.remove('hide');
dropdownContent.classList.add('show');
if (dropdownContent.scrollTop > 0) {
on_dropdownMask();
}
} else {
dropdownContent.classList.remove('show');
dropdownContent.classList.add('hide');
dropdownContent.addEventListener('animationend', function onAnimationEnd() {
if (dropdownContent.classList.contains('hide')) {
dropdownContent.style.display = 'none';
off_dropdownMask();
}
dropdownContent.removeEventListener('animationend', onAnimationEnd);
});
}
});
dropdownContent.addEventListener('scroll', function () {
if (dropdownContent.scrollTop > 14 && dropdownContent.style.display !== 'none') {
on_dropdownMask();
}
else {
off_dropdownMask();
}
});
window.addEventListener('click', function (event) {
if (!dropdownContainer.contains(event.target)) {
if (dropdownContent.style.display === 'block') {
dropdownContent.classList.remove('show');
dropdownContent.classList.add('hide');
// 强制重新开始动画
dropdownButton.classList.remove('animate');
// 使用 requestAnimationFrame 确保动画类已被移除
requestAnimationFrame(() => {
dropdownButton.classList.add('animate');
});
dropdownButton.addEventListener('animationend', function () {
this.classList.remove('animate');
}, { once: true });
dropdownContent.addEventListener('animationend', function onAnimationEnd() {
if (dropdownContent.classList.contains('hide')) {
dropdownContent.style.display = 'none';
off_dropdownMask();
}
dropdownContent.removeEventListener('animationend', onAnimationEnd);
});
}
}
});
// 版本描述区域
var versionTitle = document.createElement('p');
versionTitle.textContent = versionTitleTxt;
versionTitle.style.cssText = `
font-size: 12px;
line-height: 1.8; /* 调整行高 */
margin: 0 20px;
justify-content: center; /* 使用 flex 居中对齐 */
align-items: center;
border-top: 1px solid #D2D2D2;
text-align: center; /* 居中文本 */
color: #9B9B9B;
display: flex; /* 添加 display: flex 以使用 flexbox 布局 */
cursor: pointer; /* 鼠标指针 */
`;
var isExpanded_versionTitle = false; // 用于跟踪当前状态
// 悬浮时显示“展开所有菜单”或“折叠所有菜单”
versionTitle.addEventListener('mouseover', function () {
versionTitle.textContent = isExpanded_versionTitle ? '折叠所有菜单' : '展开所有菜单';
});
// 鼠标移开时恢复原始文本
versionTitle.addEventListener('mouseout', function () {
versionTitle.textContent = versionTitleTxt;
});
// 点击事件处理
versionTitle.addEventListener('click', function () {
// 执行点击操作,展开或折叠所有菜单
document.querySelectorAll('#main_standardFunShowButton').forEach(button => button.click());
// 切换状态并更新悬浮文本
isExpanded_versionTitle = !isExpanded_versionTitle;
versionTitle.textContent = versionTitleTxt; // 恢复原始文本
});
// 更新本地存储的开关状态
var updateSwitchState = function (switchName, newState) {
localStorage.setItem(switchName, newState.toString());
};
// 通用子菜单容器样式的函数
function initializeContainerStyle(container, state) {
if (!state) {
container.style.opacity = '0.4';// 设置透明度使内容变浅
container.style.pointerEvents = 'none';// 禁止点击操作
} else {
container.style.opacity = '';// 恢复透明度
container.style.pointerEvents = '';// 恢复点击操作
}
}
var notification_style = document.createElement('style');
notification_style.type = 'text/css';
notification_style.innerHTML = `
@keyframes showNotification {
0% {
transform: translateX(-50%) scale(0);
}
40% {
transform: translateX(-50%) scale(.96);
}
55% {
transform: translateX(-50%) scale(1.04);
}
100% {
transform: translateX(-50%) scale(1);
}
}
@keyframes hideNotification {
5% {
transform: translateX(-50%) scale(1);
}
100% {
opacity: 0;
transform: translateX(-50%) scale(0.2);
}
}
@keyframes notificationButtonAnimation {
0% { transform: translateX(-50%) scale(1); }
100% { transform: translateX(-50%) scale(1.15); opacity: 0;}
}
.notification {
cursor: default;
position: fixed;
bottom: 60px;
left: 50%;
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
padding: 10px;
border-radius: 12px;
display: none;
z-index: 9999;
backdrop-filter: blur(10px) brightness(90%); /* 添加模糊效果 */
-webkit-backdrop-filter: blur(10px); /* 兼容Safari浏览器 */
transform-origin: center;
width: auto; /* 默认宽度 */
max-width: 68%;
white-space: nowrap; /* 单行显示 */
overflow: hidden; /* 超出内容隐藏 */
text-overflow: ellipsis; /* 溢出省略号 */
text-align: center; /* 文本居中显示 */
transform: translateX(-50%); /* 初始水平居中 */
}
`;
document.head.appendChild(notification_style);
// 创建通知弹窗
var NotificationContainer = document.createElement('div');
NotificationContainer.classList.add('notification');
NotificationContainer.id = 'showNotificationContainer';
document.body.appendChild(NotificationContainer);
// 将开关和按钮加入页面
// 添加复制开关控件
const copySwitchContainer = new ToggleButtonComponent('copySwitchContainer', '点击店名复制', dropdownContent, 1);
// 添加提取商品链接控件
const newonlyItemIdButtonContainer = new ToggleButtonComponent('newmainOnlyItemIdSwitchState', '链接自动提取', dropdownContent);
// 添加手卡截图控件
const tableCardPngSwitchContainer = new ToggleButtonComponent('tableCardPngSwitchState', '快捷截图', dropdownContent,);
// 添加商品排序开关控件
const itemSortButtonContainer = new ToggleButtonComponent('mainItemSortButtonSwitchState', '商品排序', dropdownContent);
// 添加着色与计算器开关控件
const drawColorAndCalculatorContainer = new ToggleButtonComponent('mainDrawColorAndCalculatorContainer', '着色与计算器(Beta)', dropdownContent);
// 添加商品排序开关控件
const AuxiliaryFunctionsContainer = new ToggleButtonComponent('AuxiliaryFunctionsContainer', '辅助功能', dropdownContent);
dropdownContent.appendChild(versionTitle);
// 提取链接子功能区域
const main_onlyItemIdSwitch = newonlyItemIdButtonContainer.getSecondaryContent();
const sonMain_onlyItemIdSwitch = new SonToggleButtonComponent('mainOnlyItemIdSwitchState', '链接自动提取', main_onlyItemIdSwitch, "当点击商品链接窗口时,会主动提取当前剪切板中的商品链接,并更新你的剪切板", 1);
const mainOnlyItemId_autoSave = new SonToggleButtonComponent('mainOnlyItemId_autoSave_state', '自动保存', sonMain_onlyItemIdSwitch.getChildSettingsContainer(), '替换链接后自动点击“保存”按钮', 1);
const mainOnlyItemId_checkTtemLink = new SonToggleButtonComponent('mainOnlyItemId_checkTtemLink_state', '链接检查', sonMain_onlyItemIdSwitch.getChildSettingsContainer(), '链接中不存在12位ID时,使用“警告”替换当前剪切板\n\n开启此功能会引起剪切板冲突', 1);
// 快捷截图子功能区域
const main_tableCardPngSwitch = tableCardPngSwitchContainer.getSecondaryContent();
const sonMain_tableCardPngSwitch = new SonToggleButtonComponent('main_tableCardPngSwitch', '手卡截图', main_tableCardPngSwitch, "截取当前页面的手卡并添加到剪切板", 1);
const tableCardPng_resolution = new SonToggleButtonComponent('mainTableCardPng_resolution', '清晰度', sonMain_tableCardPngSwitch.getChildSettingsContainer(), "设置截图的清晰度\n\n注意:更低的清晰度并不能提高截图的响应速度", 1);
const tableCardPng_resolution_select = ['普通', '高清', '超清'];
tableCardPng_resolution.createSelectBox(tableCardPng_resolution_select);
// 自动填充子功能区域
const main_itemSort = itemSortButtonContainer.getSecondaryContent();
const sonMain_itemSortSwitch = new SonToggleButtonComponent('main_itemSort_SwitchState_1', '自动填充', main_itemSort, "点击排序时自动自动清空或输入", 1);
const itemSort_inputConter = new SonToggleButtonComponent('itemSort_inputConter', '输入内容', sonMain_itemSortSwitch.getChildSettingsContainer(), "设置自动输入的默认内容", 1);
const itemSort_inputConter_input = ['空', '0', '1', '2', '3', '999', '2536'];
itemSort_inputConter.createSelectBox(itemSort_inputConter_input);
const itemSort_countInputFun = new SonToggleButtonComponent('itemSort_countInputFun', '计数输入', sonMain_itemSortSwitch.getChildSettingsContainer(), "将“输入内容”更新为当前计数,以方便排序", 1);
itemSort_countInputFun.createNumberControDiv(10, false, 'countInput');
itemSort_countInputFun.createDivButton('开始', '退出',
(isActivated) => {
if (isActivated) {
itemSort_countInputFun.showNumberControlDiv(true); // 显示数字控制区
itemSort_countInputFun.setCount(1);
itemSort_countInputFun.countSort_reShowNotification();// 计数通知显示恢复
itemSort_inputConter.showSwitchDiv(false); // 隐藏输入内容选择框
temp_itemId = '';
} else {
itemSort_countInputFun.showNumberControlDiv(false); // 隐藏数字控制区
itemSort_inputConter.showSwitchDiv(true); // 显示输入内容选择框
}
}
);
itemSort_countInputFun.showNumberControlDiv(false);
// 着色与计算器子功能区域
const main_drawColorAndCalculator = drawColorAndCalculatorContainer.getSecondaryContent();
const sonMain_drawColor = new SonToggleButtonComponent('main_drawColor', '着色器', main_drawColorAndCalculator, "点击着色按钮后对当前手卡进行着色\n\n注意:着色器功能目前处于测试阶段,可能存在一些问题", 1);
const sonMain_drawColor_skuDesc = new SonToggleButtonComponent('main_drawColor_skuDesc', '规格栏', sonMain_drawColor.getChildSettingsContainer(), "启用对当前手卡的SKU规格栏着色", 1);
const sonMain_drawColor_livePrice = new SonToggleButtonComponent('main_drawColor_livePrice', '直播间到手价栏', sonMain_drawColor.getChildSettingsContainer(), "启用对当前手卡的直播间到手价栏着色", 1);
const sonMain_drawColor_liveGameplay = new SonToggleButtonComponent('main_drawColor_liveGameplay', '优惠方式栏', sonMain_drawColor.getChildSettingsContainer(), "启用对当前手卡的优惠方式栏着色", 1);
const sonMain_drawColor_preSetInventory = new SonToggleButtonComponent('main_drawColor_preSetInventory', '预设库存栏', sonMain_drawColor.getChildSettingsContainer(), "启用对当前手卡的预设库存栏着色", 1);
const sonMain_drawColor_inventory = new SonToggleButtonComponent('main_drawColor_inventory', '库存栏', sonMain_drawColor.getChildSettingsContainer(), "启用对当前手卡的库存栏着色", 1);
// 智能替换
const sonMain_smartReplace = new SonToggleButtonComponent('main_smartReplace', '智能替换', sonMain_drawColor.getChildSettingsContainer(), "智能识别手卡中的文字并替换为对应格式\n\n例如:将“99/2箱*6瓶”转写为“平均到手”的形式;\n将“49/2小箱/6瓶”转写为“平均到手”的形式", 1);
// 计算器开关
const sonMain_calculator = new SonToggleButtonComponent('main_calculator', '计算器', sonMain_drawColor.getChildSettingsContainer(), "点击着色按钮后对当前手卡的算式进行计算\n\n注意:计算器功能目前处于测试阶段,可能存在一些问题;\n\n例如:无法计算形如“(3+9)/2”的算式;如果你想正确计算形如这样的算式,请将算式调整为“(3+9)/(2)”", 1);
// 辅助功能子功能区域
const AuxiliaryFunctions_container = AuxiliaryFunctionsContainer.getSecondaryContent();
const sAF_backToLastCurrentURL = new SonToggleButtonComponent('sAF_backToLastCurrentURL', '最近浏览', AuxiliaryFunctions_container, "会主动提示上次浏览的场次页面,点击弹出的通知会跳转到上次浏览的场次页面", 1, true);
const sAF_closeBrowserUpdateDiv = new SonToggleButtonComponent('sAF_closeBrowserUpdateDiv', '关闭浏览器更新提示', AuxiliaryFunctions_container, "关闭浏览器更新提示,防止影响使用", 1, true);
const sAF_pastedSeachSwitchConta = new SonToggleButtonComponent('sAF_pastedSeachSwitchConta', '快捷粘贴搜索', AuxiliaryFunctions_container, "进行粘贴操作后,自动点击搜索按钮", 1, false);
const sAF_AdvanceBatchPrint = new SonToggleButtonComponent('sAF_AdvanceBatchPrint', '手卡打印功能优化', AuxiliaryFunctions_container, "优化打印页面默认文件名,允许仅打印手卡的部分区域", 1, true);
const sAF_FristPhotoCopyForTmallAndTaobao = new SonToggleButtonComponent('sAF_FristPhotoCopyForTmallAndTaobao', '天猫&淘宝主图复制', AuxiliaryFunctions_container, "在天猫或淘宝的主图上点击“复制图片”按钮,以快速将图片拷贝到剪切板\n\n注意:此功能会需要多个网页的剪切板访问权限", 1, true);
// 单击和双击事件的延迟和计数器
var delay = 200; // 延迟时间,单位毫秒
var clicks = 0;
var timer = null;
// 监听鼠标左键点击事件
document.addEventListener('click', function (event) {
// 检查是否开启了点击复制功能且在匹配的网址上
if (copySwitchContainer.getSwitchState() && isHomeURL()) {
clicks++;
if (clicks % 2 === 1) {
timer = setTimeout(function () {
// 单击操作
clicks = 0;
handleSingleClick(event);
}, delay);
} else {
// 取消之前的单击操作
clearTimeout(timer);
clicks = 0;
handleDoubleClick(event);
}
}
});
// 单击处理函数
function handleSingleClick(event) {
if (event.target && event.target.classList.contains('link-overflow-tip')) {
var text = event.target.textContent;
var copiedText = text.substring();
GM_setClipboard(copiedText);
showNotification("复制成功:" + copiedText);
itemSort_countInputFun.countSort_reShowNotification();// 计数通知显示恢复
}
}
// 双击处理函数
function handleDoubleClick(event) {
if (event.target && event.target.classList.contains('link-overflow-tip')) {
var text = event.target.textContent;
var copiedText = text.substring(0, 3);
GM_setClipboard(copiedText);
showNotification("复制成功:" + copiedText);
itemSort_countInputFun.countSort_reShowNotification();// 计数通知显示恢复
}
}
// 添加鼠标悬浮和移出事件监听器
NotificationContainer.addEventListener('mouseenter', function () {
clearTimeout(notificationTimer); // 悬浮时清除计时器
// console.log('Mouse entered notification'); // 调试日志
});
NotificationContainer.addEventListener('mouseleave', function () {
// console.log('Mouse left notification'); // 调试日志
var time = 3000;
if (itemSort_countInputFun.getDivButtonState()) time = 0;
resetTimer(time); // 移出时重置计时器
});
function showNotification(message, duringTime = 3000, showImage = false) {
// 清除之前的计时器
if (notificationTimer) {
clearTimeout(notificationTimer);
}
// 重置隐藏标志
isHiding = false;
// 重置通知样式
NotificationContainer.innerHTML = '';
NotificationContainer.style.width = 'auto';
NotificationContainer.style.transform = 'translateX(-50%)';
NotificationContainer.style.animation = 'none';
NotificationContainer.style.padding = '10px';
// 短暂移除并重新添加通知元素,强制触发动画
document.body.removeChild(NotificationContainer);
setTimeout(() => {
document.body.appendChild(NotificationContainer);
// 设置通知文本内容
NotificationContainer.innerHTML = message;
// 如果指定了显示图片,则读取剪贴板中的图片并显示
if (showImage) {
NotificationContainer.style.padding = '5px';
navigator.clipboard.read().then(async function (data) {
for (const item of data) {
for (const type of item.types) {
if (type.startsWith('image/')) {
const blob = await item.getType(type);
const imageURL = URL.createObjectURL(blob);
const imageElement = document.createElement('img');
imageElement.src = imageURL;
imageElement.style.width = '300px';
imageElement.style.borderRadius = '8px';
const imageContainer = document.createElement('div');
imageContainer.style.paddingTop = '10px';
imageElement.style.maxWidth = 'auto';
imageContainer.style.borderRadius = '8px';
imageContainer.style.margin = 'auto';
imageContainer.style.display = 'block';
imageContainer.appendChild(imageElement);
NotificationContainer.appendChild(imageContainer);
// 图片加载完成后调整位置并设置消失定时器
imageElement.onload = function () {
NotificationContainer.style.left = '50%';
NotificationContainer.style.display = 'block';
NotificationContainer.style.animation = 'showNotification 0.5s forwards';
// 设置消失动画计时器
resetTimer(duringTime);
};
break;
}
}
}
}).catch(function (error) {
console.error('Error reading clipboard:', error);
});
} else {
// 显示通知
NotificationContainer.style.display = 'block';
NotificationContainer.style.animation = 'showNotification 0.5s forwards';
// 设置消失动画计时器
resetTimer(duringTime);
}
}, 50); // 确保通知元素短暂移除再添加
}
function hideNotification() {
if (isHiding) return;
isHiding = true;
NotificationContainer.style.animation = 'hideNotification 0.5s forwards';
// 在动画结束后隐藏元素
notificationTimer = setTimeout(function () {
NotificationContainer.style.display = 'none';
isHiding = false;
}, 500);
}
function resetTimer(duringTime = 3000) {
if (notificationTimer) {
clearTimeout(notificationTimer);
console.log("清除计时器");
}
if (duringTime > 0) {
notificationTimer = setTimeout(function () {
hideNotification();
console.log("设置计时器");
}, duringTime); // 3秒后自动隐藏通知
}
}
async function clickButton(pastedData = true, delayTime, containerSelector = document, buttonSelector) {
// 判断粘贴内容是否为空或为 true
if (pastedData === true || (typeof pastedData === 'string' && pastedData.trim().length > 0)) {
// 查找指定容器内的按钮
var container = containerSelector === document ? document : document.querySelector(containerSelector);
if (container) {
var button = container.querySelector(buttonSelector);
if (button) {
setTimeout(function () {
button.click();
}, delayTime);
}
}
}
}
// 监听粘贴事件
document.addEventListener('paste', function (event) {
// 判断是否开启了自动点击功能且在匹配的网址上
if (sAF_pastedSeachSwitchConta.getSwitchState() && isHomeURL()) {
// 获取粘贴板中的内容
var pastedData = (event.clipboardData || window.clipboardData).getData('text');
var className = '.ant-btn.css-9fw9up.ant-btn-primary';
clickButton(pastedData, 100, undefined, className);
}
});
// 检查文本中是否是天猫链接函数
function checkForTmallInClipboard(text) {
const regex = /https:\/\/[^ ]*tmall[^ ]*id=\d{12}/;
return regex.test(text);
}
function checkForChaoshiInClipboard(text) {
const regex = /https:\/\/[^ ]*chaoshi[^ ]*id=\d{12}/;
return regex.test(text);
}
function checkForFeizhuInClipboard(text) {
const regex = /https:\/\/[^ ]*fliggy[^ ]*id=\d{12}/;
return regex.test(text);
}
// 提取链接id函数
function extractIdFromClipboard(text) {
const idMatch = text.match(/id=(\d{12})/);
return idMatch ? idMatch[1] : null;
}
// 粘贴功能
async function simulatePaste(targetElement, clearBeforePaste = true) {
try {
// 从剪贴板读取文本
let clipboardText = await navigator.clipboard.readText();
// 检查目标元素是否为可编辑元素
if (targetElement.isContentEditable || targetElement.tagName === 'INPUT' || targetElement.tagName === 'TEXTAREA') {
// 如果clearBeforePaste为true,清空目标元素的内容
if (clearBeforePaste) {
if (targetElement.isContentEditable) {
targetElement.innerHTML = '';
} else {
targetElement.value = '';
}
}
// 插入剪贴板内容到目标元素
if (document.execCommand('insertText', false, clipboardText)) {
// console.log('粘贴成功:' + clipboardText);
} else {
targetElement.value += clipboardText;
}
} else {
// alert('目标元素不可编辑');
}
} catch (err) {
console.error('读取剪贴板内容失败:', err);
showNotification("读取剪贴板内容失败");
}
}
function updateClipboardContent() {
var tmail = "https://detail.tmall.com/item.htm?id=";
var chaoshi = "https://chaoshi.detail.tmall.com/item.htm?id=";
var taobao = "https://item.taobao.com/item.htm?id=";
var feizhu = "https://traveldetail.fliggy.com/item.htm?id=";
navigator.clipboard.readText().then((clipText) => {
const isTmall = checkForTmallInClipboard(clipText);
const isChaoshi = checkForChaoshiInClipboard(clipText);
const isFeizhu = checkForFeizhuInClipboard(clipText);
const itemId = extractIdFromClipboard(clipText);
if (itemId) {
var newUrl;
if (isTmall && !isChaoshi) {
// 转换为天猫链接
newUrl = tmail + itemId;
}
else if (isChaoshi) {
// 转换为猫超链接
newUrl = chaoshi + itemId;
}
else if (isFeizhu) {
// 转换为飞猪链接
newUrl = tmail + itemId;
}
else {
// 转换为淘宝链接
newUrl = taobao + itemId;
}
GM_setClipboard(newUrl);
showNotification("剪贴板内容已更新为:" + newUrl);
//console.log('剪贴板内容已更新为:' + newUrl);
} else {
if (mainOnlyItemId_checkTtemLink.getSwitchState()) {
// 防止错误粘贴功能
GM_setClipboard("12位数字ID不全");
}
showNotification("剪贴板中没有找到12位数字ID");
//console.log('剪贴板中没有找到12位数字ID');
}
}).catch((err) => {
console.error('读取剪贴板失败:', err);
});
}
// 监听鼠标左键点击事件
document.addEventListener('click', function (event) {
// 提取商品链接粘贴功能区域
if (sonMain_onlyItemIdSwitch.getSwitchState() && isHomeURL()) {
if (event.target.closest('.ant-form-item.liveLinkFormItem___RPAQZ.css-9fw9up.ant-form-item-has-success')) {
if (event.target.classList.contains('ant-input-affix-wrapper') ||
event.target.classList.contains('ant-input-affix-wrapper-status-error') ||
event.target.classList.contains('css-9fw9up')) {
// console.log('目标元素被点击');
updateClipboardContent();
simulatePaste(document.activeElement);
// 点击保存按钮
if (mainOnlyItemId_autoSave.getSwitchState()) {
var fbutton = '.ant-drawer-footer';
var buttonName = '.ant-btn.css-9fw9up.ant-btn-primary';
showNotification("粘贴成功&保存成功");
clickButton(undefined, 500, fbutton, buttonName);
}
}
}
}
// 自动序号标1功能
if (sonMain_itemSortSwitch.getSwitchState()) {
if (event.target.closest('.ant-input-number.ant-input-number-sm.css-1ayq15k')) {
if (event.target.classList.contains('ant-input-number-input')) {
// console.log('目标元素被点击');
if (!itemSort_countInputFun.getDivButtonState()) {
GM_setClipboard(itemSort_inputConter.getSelectBoxValue());
} else {
GM_setClipboard(itemSort_countInputFun.getCount() - 1);
}
simulatePaste(document.activeElement);
}
}
}
// 自动激活排序输入框
if (sonMain_itemSortSwitch.getSwitchState()) {
if (event.target.classList.contains('sortWeights___Kn8mn') ||
event.target.closest('.sortWeights___Kn8mn')) {
// console.log('找到sortWeights___Kn8mn');
activateInputFieldAndSave(event);
}
}
});
/* 快捷截图功能区 */
// 返回渲染倍数
function selectedTableCardPngResolution() {
const resolution = tableCardPng_resolution.getSelectBoxValue();
// console.log("设定的分辨率:" + resolution);
switch (resolution) {
case '普通':
return 1.5;
case '高清':
return 2.5;
case '超清':
return 4;
default:
return 2.5;
}
}
function loadImageIcon() {
return '<span class="ant-btn-icon ant-btn-loading-icon" style=""><span role="img" aria-label="loading" class="anticon anticon-loading anticon-spin"><svg viewBox="0 0 1024 1024" focusable="false" data-icon="loading" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"></path></svg></span></span>';
}
if (sonMain_tableCardPngSwitch.getSwitchState() && isTableCardURL()) {
// Load html2canvas library
function loadHtml2Canvas(callback) {
var script = document.createElement('script');
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js';
script.onload = callback;
document.head.appendChild(script);
}
function createCaptureScreenshotButton() {
const targetClass = '[class*="ant-space"][class*="css-9fw9up"][class*="ant-space-horizontal"][class*="ant-space-align-center"]';
const captureScreenshot_observer = new MutationObserver((mutationsList, observer) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
const targetElement = document.querySelector(targetClass);
if (targetElement) {
if (document.querySelector('.captureScreenshot')) {
captureScreenshot_observer.disconnect();
return;
}
var captureScreenshot = document.createElement('div');
captureScreenshot.classList.add('ant-space-item');
var captureScreenshotButton = document.createElement('button');
captureScreenshotButton.textContent = '快捷截图';
captureScreenshotButton.classList.add('ant-btn', 'css-9fw9up', 'ant-btn-default', 'captureScreenshot');
captureScreenshot.appendChild(captureScreenshotButton);
targetElement.insertBefore(captureScreenshot, targetElement.firstChild);
captureScreenshotButton.addEventListener('click', captureScreenshotFunction);
captureScreenshot_observer.disconnect();
break;
}
}
}
});
captureScreenshot_observer.observe(document.body, {
childList: true,
subtree: true
});
}
function loadImageAsDataURL(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
responseType: 'blob',
onload: function (response) {
const blob = response.response;
const reader = new FileReader();
reader.onloadend = function () {
resolve(reader.result);
};
reader.onerror = function () {
reject(new Error('Failed to load image'));
};
reader.readAsDataURL(blob);
},
onerror: function () {
reject(new Error('Network error'));
}
});
});
}
async function captureScreenshotFunction() {
const tableElement = document.querySelector('table');
var displayScale = selectedTableCardPngResolution();
// console.log("设定的倍率:" + displayScale);
showNotification("截图中 " + loadImageIcon(), 0);
if (tableElement) {
const rows = tableElement.querySelectorAll('tr');
if (rows.length >= 3) {
rows[2].cells[0].textContent = '';
// 隐藏除第二行和第三行外的所有行
rows.forEach((row, index) => {
if (index !== 1 && index !== 2) {
row.style.display = 'none';
}
});
const imgElement = rows[2].cells[2].querySelector('img');
if (imgElement) {
try {
const dataUrl = await loadImageAsDataURL(imgElement.src);
imgElement.src = dataUrl;
setTimeout(() => {
// 使用 html2canvas 捕获截图
html2canvas(tableElement, { scale: displayScale }).then(canvas => {
// 恢复所有行的显示状态
rows.forEach(row => {
row.style.display = '';
});
canvas.toBlob(async function (blob) {
try {
await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
console.log("%cTable Screenshot:", "color: #9147ff", "Screenshot copied to clipboard.");
showNotification("截图已成功复制到剪贴板", undefined, true);
} catch (error) {
console.log("%cTable Screenshot: Screenshot failed to copy to clipboard!", "color: #ff8080");
showNotification("截图失败!");
}
});
});
}, 200); // 延迟 200 毫秒等待图片加载完毕
} catch (error) {
console.log('Image load error:', error);
}
} else {
console.log('Image element not found');
}
} else {
console.log("Table does not have enough rows");
}
} else {
console.log("Table element not found");
}
}
loadHtml2Canvas(createCaptureScreenshotButton);
}
/*
**************************
自动激活排序窗口、点击保存
**************************
*/
function activateInputFieldAndSave(event) {
if (true) {
const click_itemId = handleCellClick(event);
if (temp_itemId != click_itemId) {
if (itemSort_countInputFun.getDivButtonState()) {
itemSort_countInputFun.updateCount(1, 'countInput');
}
temp_itemId = click_itemId;
}
// countText.textContent = countNum_Sort + 1;
// console.log('计数:'+countNum_Sort);
const popover = document.querySelector('.ant-popover:not(.ant-popover-hidden)');
const inputField = popover.querySelector('.ant-input-number-input');
if (inputField) {
inputField.focus();
inputField.click();
} else {
console.log('未找到输入字段');
}
}
}
// 查找点击的id
function handleCellClick(event) {
// 查找最接近的包含行元素的类
let rowElement = event.target.closest('.ag-row');
if (rowElement) {
// 获取row-index属性
let rowIndex = rowElement.getAttribute('row-index');
// console.log('找到的行索引:', rowIndex);
// 使用row-index属性查找行内的span标签
let targetSpan = document.querySelector(`.ag-row[row-index="${rowIndex}"] span#MarkHighlight-upLiveId-upLiveId`);
if (targetSpan) {
return targetSpan.textContent;
// 打印span的文本内容
// console.log('目标span的文本内容:', targetSpan.textContent);
} else {
// console.log(`在行索引为${rowIndex}的行中未找到id为"MarkHighlight-upLiveId-upLiveId"的span标签。`);
}
} else {
// console.log('未找到点击单元格对应的行。');
}
}
/*
=================
打印标题优化
=================
*/
function titlePrint_extractData() {
const dateElement = document.querySelector('.isSelect___qbUI1 .ant-space.css-9fw9up.ant-space-horizontal.ant-space-align-center.title___mA8xY .ant-space-item:nth-child(2) div');
const sessionElement = document.querySelector('.truncate.sessionName___HUMKC.font-ma-semibold');
if (dateElement && sessionElement) {
const dateText = dateElement.textContent.trim();
const sessionText = sessionElement.textContent.trim();
GM_setValue('titlePrint_extractedDate', dateText);
GM_setValue('titlePrint_extractedSession', sessionText);
// console.log('Date extracted and stored:', dateText);
// console.log('Session name extracted and stored:', sessionText);
}
}
/*
=================
手卡标题优化
=================
*/
// 网址id提取
function url_getSessionGoodsId() {
const url = window.location.href;
const match = url.match(/sessionGoodsId=(\d+)/);
return match ? match[1] : null;
}
// 检查当前页面标题是否为“表格手卡查看 - 羚客Link”
function isTableCardTitle() {
return document.title === '表格手卡查看 - 羚客Link';
}
// 检测并修改标题
function checkAndModifyTitle() {
if (!true) return;
const sessionGoodsId = url_getSessionGoodsId();
if (sessionGoodsId && isTableCardTitle() && isTableCardURL()) {
document.title = '【手卡】商品ID:' + sessionGoodsId;
// console.log("标题更新");
}
}
/*
系统功能优化
*/
// 创建一个MutationObserver实例
// 绑定点击事件的外部函数
function bindClickEventToNotification(url) {
console.log('绑定点击事件, 传入URL:' + url);
const element = document.getElementById('showNotificationContainer');
element.style.cursor = 'pointer';
if (element) {
// 定义点击事件处理函数
function handleClick() {
isHiding = true;
NotificationContainer.style.animation = 'notificationButtonAnimation 0.5s forwards';
window.location.href = url;
setTimeout(function () {
NotificationContainer.style.display = 'none';
isHiding = false;
window.location.reload();
}, 500);
// 移除点击事件
element.removeEventListener('click', handleClick);
element.style.cursor = 'default';
}
// 绑定点击事件
element.addEventListener('click', handleClick);
setTimeout(function () {
// 移除点击事件
element.removeEventListener('click', handleClick);
element.style.cursor = 'default';
hideNotification();
}, 5000);
}
}
// 设置打印手卡的部分区域
function setPrintTableCardArea(isActivated) {
var isShow = isActivated ? 'flex' : 'none';
// 获取所有的table元素
var tables = document.querySelectorAll('table');
tables.forEach(function (table) {
// 获取每个table中的tbody
var tbody = table.querySelector('tbody');
// 获取tbody中的所有tr行
var rows = tbody.querySelectorAll('tr');
// 遍历tr行并隐藏第三行之后的所有行
rows.forEach(function (row, index) {
if (index >= 3) { // 从第四行开始(索引为3),设置display为none
row.style.display = isShow;
}
});
});
}
// 判断是否是剧透时间
function checkIfTrailer(storedDate) {
const currentTime = new Date();
let isTrailer = '';
// 获取当前年份
const currentYear = currentTime.getFullYear();
// 将字符串日期转换为Date对象,加入当前年份
let adjustedDate = new Date(`${currentYear}-${storedDate}T18:00:00`);
// 将日期往前调整一天
adjustedDate.setDate(adjustedDate.getDate() - 1);
// 计算两个日期之间的差值(以天为单位)
const timeDifference = Math.abs(currentTime - adjustedDate);
const dayDifference = timeDifference / (1000 * 60 * 60 * 24);
// 如果天数差值大于180天,考虑跨年情况,给adjustedDate加上1年
if (dayDifference > 180) {
adjustedDate.setFullYear(adjustedDate.getFullYear() + 1);
}
const printCard_switch = document.getElementById('button_setPrintTableCardArea_switch');
const button_setPrintTableCardArea = document.getElementById('button_setPrintTableCardArea')
if(button_setPrintTableCardArea && printCard_switch.getAttribute('aria-checked') === 'true'){
isTrailer = "核对";
}else{
// 比较当前时间与截止时间
if (currentTime < adjustedDate) {
isTrailer = "剧透";
} else {
isTrailer = '';
}
}
return isTrailer;
}
const sys_auxiliaryFunctions = new MutationObserver((mutationsList) => {
let urlChanged = false;
// 场次信息数据
const storedDate = GM_getValue('titlePrint_extractedDate', '');
const storedSession = GM_getValue('titlePrint_extractedSession', '');
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
// 系统通知位置优化
if (node.nodeType === 1 && node.classList.contains('ant-message') && node.classList.contains('ant-message-top') && node.classList.contains('css-190m0jy')) {
// 修改top值为64px
node.style.top = '64px';
}
if (sAF_closeBrowserUpdateDiv.getSwitchState()) {
// 关闭浏览器更新弹窗
if (node.nodeType === 1 && node.id === 'link-browser-update-global') {
const closeButton = node.querySelector('.link-browser-update-global-close');
if (closeButton) {
closeButton.click();
showNotification('已关闭浏览器更新弹窗', 1500);
// console.log('关闭了浏览器更新弹窗');
} else {
console.log('未找到关闭按钮');
}
}
}
});
// 检查URL是否变化
if (isHomeURL()) {
const currentURL = window.location.href; // 获取当前网址
titlePrint_extractData(); // 提取日期和场次信息
// 只有在 URL 发生变化时,才会执行以下代码
if (currentURL !== lastCurrentURL) {
// 在保存新的 currentURL 之前,更新 lastCurrentURL
const previousURL = lastCurrentURL;
// 将当前网址保存到 localStorage
localStorage.setItem('lastCurrentURL', currentURL);
if (sAF_backToLastCurrentURL.getSwitchState()) {
// 显示通知并绑定点击事件,传入 previousURL 而不是 currentURL
showNotification('上次浏览的页面:' + storedDate + ' ' + storedSession, 5000);
setTimeout(() => {
itemSort_countInputFun.countSort_reShowNotification();// 计数通知显示恢复
}, 4000);
setTimeout(() => {
bindClickEventToNotification(previousURL); // 绑定点击事件,传入 previousURL
}, 50);
}
// 更新 lastCurrentURL 为新的网址
lastCurrentURL = currentURL;
urlChanged = true;
}
GM_setValue('sAF_FristPhotoCopyForTmallAndTaobao', sAF_FristPhotoCopyForTmallAndTaobao.getSwitchState());
}
if (isTableCardURL()) {
// 手卡标题优化
// checkAndModifyTitle();
// 调用函数添加SVG图标
addSVGToSpecificTDs();
// 一键着色按键显示
displayDrawColorButton();
}
if(isTmallItemURL()){
const isCreateButton = GM_getValue('sAF_FristPhotoCopyForTmallAndTaobao', false);
if(isCreateButton)
{
// 创建按钮
createGetTmallPngButton();
}
}
if (sAF_AdvanceBatchPrint.getSwitchState() && isBatchPrintURL() && storedDate && storedSession) {
// 批量打印标题优化
document.title = `${storedDate} ${storedSession}手卡${checkIfTrailer(storedDate)}`;
setTimeout(function () {
// 查找目标元素,即将新div插入到这个元素中
var targetElement = document.querySelector('.flex.justify-end');
// 检查是否已经存在id为button_setPrintTableCardArea的div,避免重复添加
if (!document.getElementById('button_setPrintTableCardArea')) {
// 创建一个新的div元素
var newDiv = document.createElement('div');
newDiv.id = 'button_setPrintTableCardArea';
newDiv.style.display = 'flex';
newDiv.style.justifyContent = 'space-between';
newDiv.style.alignItems = 'center';
newDiv.style.marginRight = '10px';
// 创建左侧的文本节点
var textNode = document.createElement('span');
textNode.textContent = '不打印红字和卖点区域';
textNode.style.fontSize = '14px';
textNode.style.marginRight = '10px';
// 创建右侧的开关按钮
var switchButton = document.createElement('button');
switchButton.type = 'button';
switchButton.id = 'button_setPrintTableCardArea_switch';
switchButton.setAttribute('role', 'switch');
switchButton.setAttribute('aria-checked', 'false'); // 默认未开启
switchButton.className = 'ant-switch ant-switch-small css-175k68i';
// 创建开关按钮内部的div(用于手柄)
var handleDiv = document.createElement('div');
handleDiv.className = 'ant-switch-handle';
// 将手柄div添加到按钮中
switchButton.appendChild(handleDiv);
// 添加点击事件,切换开关状态
switchButton.addEventListener('click', function () {
var isChecked = switchButton.getAttribute('aria-checked') === 'true';
if (isChecked) {
// 如果是开启状态,关闭它
switchButton.setAttribute('aria-checked', 'false');
switchButton.classList.remove('ant-switch-checked');
setPrintTableCardArea(true);
} else {
// 如果是关闭状态,开启它
switchButton.setAttribute('aria-checked', 'true');
switchButton.classList.add('ant-switch-checked');
setPrintTableCardArea(false);
}
});
// 将文本节点和开关按钮添加到div中
newDiv.appendChild(textNode);
newDiv.appendChild(switchButton);
// 将新创建的div添加到目标元素中
targetElement.appendChild(newDiv);
} else {
// console.log('开关已经存在,跳过创建。');
}
}, 1000); // 延迟1秒执行
}
}
}
// 处理URL变化
if (urlChanged) {
// 检查是否存在switchesContainer
if (!document.getElementById('switchesContainer')) {
if (isHomeURL()) {
document.body.appendChild(switchesContainer);
}
}
}
});
// 观察目标节点的子节点添加和移除
sys_auxiliaryFunctions.observe(document.body, { childList: true, subtree: true });
/*
一键着色
*/
function createDrawColorButton() {
const targetClass = '[class*="ant-space"][class*="css-9fw9up"][class*="ant-space-horizontal"][class*="ant-space-align-center"]';
const drawColor_observer = new MutationObserver((mutationsList, observer) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
const targetElement = document.querySelector(targetClass);
if (targetElement) {
if (document.querySelector('.drawColor')) {
drawColor_observer.disconnect();
return;
}
var drawColor = document.createElement('div');
drawColor.classList.add('ant-space-item');
var drawColorButton = document.createElement('button');
drawColorButton.textContent = '一键着色';
drawColorButton.style.display = 'none';
drawColorButton.classList.add('ant-btn', 'css-9fw9up', 'ant-btn-default', 'drawColor');
drawColor.appendChild(drawColorButton);
targetElement.insertBefore(drawColor, targetElement.firstChild);
drawColorButton.addEventListener('click', startDrawColor);
drawColor_observer.disconnect();
break;
}
}
}
});
drawColor_observer.observe(document.body, {
childList: true,
subtree: true
});
}
// 在页面上创建按钮
createDrawColorButton();
function displayDrawColorButton() {
// 获取所有 class 为 'ant-btn-primary' 的按钮
const buttons = document.querySelectorAll('.ant-btn-primary');
const drawColorButtons = document.querySelector('.drawColor');
// 遍历所有按钮
for (const button of buttons) {
// 找到按钮内部的 span 标签
const span = button.querySelector('span');
// 如果 span 标签存在,检查文本内容是否包含“编辑手卡”
if (span && span.textContent.includes('编辑手卡') || !sonMain_drawColor.getSwitchState()) {
drawColorButtons.style.display = 'none';
// 更新 divWrapper 的显示状态
updateDivWrapperDisplay(false);
return true;
}
}
// 如果没有找到包含“编辑手卡”的文本,返回 false
drawColorButtons.style.display = 'inline-block';
// 更新 divWrapper 的显示状态
updateDivWrapperDisplay(true);
return false;
}
//着色器执行函数
function startDrawColor() {
if (sonMain_drawColor.getSwitchState()) {
if (sonMain_drawColor_skuDesc.getSwitchState()) {
activateIframeAndModifyStyles('skuDesc');
}
if (sonMain_drawColor_livePrice.getSwitchState()) {
activateIframeAndModifyStyles('livePrice');
}
if (sonMain_drawColor_liveGameplay.getSwitchState()) {
activateIframeAndModifyStyles('liveGameplay');
}
if (sonMain_drawColor_preSetInventory.getSwitchState()) {
activateIframeAndModifyStyles('preSetInventory');
}
if (sonMain_drawColor_inventory.getSwitchState()) {
activateIframeAndModifyStyles('inventory');
}
}
// 通知
showNotification('着色成功');
}
/*字体颜色库*/
const colorLibrary = {
black: 'rgb(51, 51, 51)',
gray: 'rgb(173, 173, 173)',
red: 'rgb(236, 40, 39)',
blue: 'rgb(0, 145, 255)',
green: 'rgb(13, 193, 97)',
orange: 'rgb(243, 141, 15)',
yellow: 'rgb(228, 228, 50)',
cyan: 'rgb(25, 229, 221)',
purple: 'rgb(180, 95, 224)',
pink: 'rgb(241, 66, 125)',
bluePurple: 'rgb(106, 101, 227)',
grassGreen: 'rgb(157, 189, 78)',
skyBlue: 'rgb(79, 191, 227)',
brown: 'rgb(161, 90, 28)',
};
// 定义不同激活元素的颜色映射
var colorMaps = {
'skuDesc': [
{ regex: /([1-9]?[0-9])?个(sku|SKU|颜色|尺码|组合|口味|规格|色号|款式|版型)/, color: colorLibrary.red },
{ regex: /.*总(价值|售价)(([\d\*\+\-\=\s\./]+)?[wW+]?)元?/, color: colorLibrary.bluePurple },
{ regex: /正装.*((([\d\*\+\-\=\s\./]+)?[wW+]?)元?)?.*价值(([\d\*\+\-\=\s\./]+)?[wW+]?)元?|日常售价(([\d\*\+\-\=\s\./]+)?[wW+]?)元?/, color: colorLibrary.skyBlue },
{ regex: /尺寸(:)?|重量(:)?|克重(:)?|长度(:)?|承重(:)?|容量(:)?|(?:适用|食用|服用|建议|用法)(?:人群|方法|说明|建议|用法|用量):?|链长:|产地:/, color: colorLibrary.blue },
{ regex: /规格:.*/, color: colorLibrary.blue },
{ regex: /.*医嘱.*|.*糖尿病.*|.*过敏.*|.*禁止.*|.*勿食.*|.*慎食.*|.*不宜.*|.*监护.*|.*敏感.*|.*(不)?建议.*|.*慎用.*|.*停止.*|材质(成分|信息)?(:)?|面料成分(:)?/, color: colorLibrary.red },
{ regex: /.*膜布(材质)?:.*|.*标配:.*|.*特证.*|.*内含.*|.*(物理|化学|物化结合)防晒.*|.*(美白|防晒)特证.*|.*皂基.*/, color: colorLibrary.purple },
{ regex: /.*(UPF|SPF|PA\+).*/i, color: colorLibrary.orange },
],
'livePrice': [
{ regex: /平均/, color: colorLibrary.black },
// { regex: /不沟通价值/, color: colorLibrary.green },
{ regex: /.*总价值(([\d\*\+\-\=\s\./]+)?[wW+]?)元?/, color: colorLibrary.bluePurple },
{ regex: /正装.*((([\d\*\+\-\=\s\./]+)?[wW+]?)元?)?.*价值(([\d\*\+\-\=\s\./]+)?[wW+]?)元?|非卖品/, color: colorLibrary.skyBlue },
{ regex: /折扣力度.*/, color: colorLibrary.purple },
{ regex: /(拍|买).*送/, color: colorLibrary.red },
{ regex: /.*(?:可|免费|支持)试用.*|.*88vip到手.*/, color: colorLibrary.orange },
{
regex: /.*(?:件|套|量)!!.*|.*再加赠.*|第一件.*|.*到手.*|补贴.*|.*(?:蜜蜂|商家)客服.*|.*猫超卡.*|.*确收.*|.*相当于买.*/,
color: colorLibrary.red
},
{ regex: /(超正装量)|(近正装量)|(正装量)|^氨基酸$|同系列/, color: colorLibrary.orange },
{ regex: /.*件(0元|1元)/, color: colorLibrary.blue },
{ regex: /.*免息|.*赠品不叠加|(不同规格)/, color: colorLibrary.brown },
],
'inventory': {
default: colorLibrary.black, // 默认颜色
color1: colorLibrary.green, // 颜色1
color2: colorLibrary.blue, // 颜色2
},
'preSetInventory': colorLibrary.black, // 颜色用于preSetInventory
'liveGameplay': [
{ regex: /详情.*券|.*百(亿)?补(贴)?.*|.*专属价.*|.*直播间.*/, color: colorLibrary.red },
{ regex: /拍立减|直接拍|.*满减.*|\+/, color: colorLibrary.black },
{ regex: /拍(一|二|三|四|五|六|七|八|九|十|十一|十二|十三|十四|十五|[1-9]?[0-9])/, color: colorLibrary.blue },
{ regex: /.*合计.*/, color: colorLibrary.bluePurple },
]
};
var colorMaps2 = {
'skuDesc': [
{ regex: /价值(([\d\*\+\-\=\s\./]+)?[wW+]?)元?|售价(([\d\*\+\-\=\s\./]+)?[wW+]?)元?|不沟通价值/, color: colorLibrary.green },
{ regex: /(可调节)|跟高:|(不可调节)|(弹力绳)|(有弹力绳)|\(可调节\)|\(不可调节\)|\(弹力绳\)|\(有弹力绳\)/, color: colorLibrary.orange },
{ regex: /^氨基酸$|.*调:|^(一|二)元罐$|^一物一签$|^一物一证$/, color: colorLibrary.orange },
{ regex: /材质(成分)?(:)?|面料成分(:)?/, color: colorLibrary.blue },
],
'livePrice': [
{ regex: /价值(([\d\*\+\-\=\s\./]+)?[wW+]?)元?|不沟通价值/, color: colorLibrary.green },
{ regex: /同款正装|同款|正装/, color: colorLibrary.blue },
{ regex: /相当于(([\d\*\+\-\=\s\./]+)?[wW+]?)元?/, color: colorLibrary.gray },
],
'inventory': {
default: colorLibrary.black, // 默认颜色
color1: colorLibrary.green, // 颜色1
color2: colorLibrary.blue, // 颜色2
},
'preSetInventory': colorLibrary.black, // 颜色用于preSetInventory
'liveGameplay': [
]
};
var colorMaps3 = {
'skuDesc': [
],
'livePrice': [
],
'liveGameplay': [
]
};
// 正则表达式:匹配纯数字和带有'w'的数字
const numericRegex = /^[0-9]*\.?[0-9]*[wW]?\+?$/;
const priceGameplayRegex = /.*:(([\d\*\+\-\=\s\./]+)[wW+]?)元?/;
const check_skuDescFirstLine = /([1-9]?[0-9])?个(sku|SKU|颜色|尺码|组合|规格|款式|版型)/;
// 移除所有元素的 style 和 data-mce-style 属性
function removeStyles(element) {
element.removeAttribute('style');
element.removeAttribute('title');
element.removeAttribute('data-mce-style');
for (let i = 0; i < element.children.length; i++) {
removeStyles(element.children[i]);
}
}
// 根据优先级排序colorMap,长文本优先
function sortColorMap(colorMap) {
return colorMap.slice().sort((a, b) => b.regex.source.length - a.regex.source.length);
}
// 应用颜色到现有的 span 或创建新的 span
function applyColor(span, color) {
if (!span.getAttribute('data-mce-style')) {
span.style.color = color;
span.setAttribute('data-mce-style', `color: ${color};`);
}
}
// 添加新样式
// 此函数用于向iframe文档中的所有<p>元素添加新的样式。
// 参数:
// - iframeDocument: iframe的文档对象
// - colorMap: 包含正则表达式和对应颜色的映射对象
function addNewStyles(iframeDocument, colorMap) {
const ps = iframeDocument.querySelectorAll('p');
ps.forEach(p => {
const innerHTML = p.innerHTML;
let newInnerHTML = '';
const parts = innerHTML.split(/(<br>| )/);
parts.forEach(part => {
let styledPart = part;
const sortedColorMap = sortColorMap(colorMap);
sortedColorMap.forEach(map => {
if (map.regex.test(part)) {
const color = map.color;
// 创建一个临时的div用于处理HTML片段
const div = document.createElement('div');
div.innerHTML = part;
// 查找所有的<span>元素
const spans = div.querySelectorAll('span');
if (spans.length) {
spans.forEach(span => {
applyColor(span, color);
});
styledPart = div.innerHTML;
} else {
const match = map.regex.exec(part);
if (match) {
const span = document.createElement('span');
span.innerHTML = match[0];
applyColor(span, color);
styledPart = part.replace(map.regex, span.outerHTML);
}
}
}
});
newInnerHTML += styledPart;
});
p.innerHTML = newInnerHTML;
});
}
function applyPrefixSuffixColor(iframeDocument) {
const ps = iframeDocument.querySelectorAll('p');
ps.forEach(p => {
const innerHTML = p.innerHTML;
let newInnerHTML = '';
const parts = innerHTML.split(/(<br>| )/);
parts.forEach(part => {
const testApply = part.indexOf('折扣');
if (testApply !== -1 || priceGameplayRegex.test(part.textContent)) {
newInnerHTML += part;
return; // 跳过折扣行
}
const colonIndex = part.indexOf(':');
if (colonIndex !== -1) {
const prefix = part.substring(0, colonIndex + 1); // 包含“:”
const suffix = part.substring(colonIndex + 1);
// 创建临时 div 用于获取后缀的纯文本
const tempDiv = document.createElement('div');
tempDiv.innerHTML = suffix;
const plainTextSuffix = tempDiv.textContent || tempDiv.innerText || "";
// 检查后缀并应用颜色
let styledSuffix = suffix;
const suffixSpan = document.createElement('span');
suffixSpan.innerHTML = suffix;
if (numericRegex.test(plainTextSuffix)) {
applyColor(suffixSpan, colorLibrary.red);
styledSuffix = suffixSpan.outerHTML;
} else {
applyColor(suffixSpan, colorLibrary.gray);
styledSuffix = suffixSpan.outerHTML;
}
// 创建前缀 span 并应用颜色
const prefixSpan = document.createElement('span');
prefixSpan.innerHTML = prefix;
if (numericRegex.test(plainTextSuffix)) {
applyColor(prefixSpan, colorLibrary.blue);
} else {
applyColor(prefixSpan, colorLibrary.gray);
}
newInnerHTML += prefixSpan.outerHTML + styledSuffix;
} else {
newInnerHTML += part;
}
});
p.innerHTML = newInnerHTML;
});
}
const activateIframeAndModifyStyles = activateElementId => {
const activateElement = document.querySelector(`#${activateElementId} .link-node-hover-text-container`);
if (activateElement) {
activateElement.click();
activateElement.focus();
const iframe = document.querySelector(`#${activateElementId} .tox-edit-area iframe`);
if (iframe) {
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
if (iframeDocument) {
// 清除原有的样式
if (sonMain_drawColor.getSwitchState()) {
removeStyles(iframeDocument.body);
}
if (sonMain_calculator.getSwitchState()) {
findAndCalculateExpressions(iframeDocument, calculate);
}
if (sonMain_drawColor.getSwitchState()) {
// 第一行红色标记
if (activateElementId === 'livePrice') {
if (sonMain_smartReplace.getSwitchState()) {
autoWriteAvgPrice(iframeDocument);
}
modifyFirstPTagAndSpans(iframeDocument);
applyPrefixSuffixColor(iframeDocument);
}
// 规格首行非sku描述行蓝色
if (activateElementId === 'skuDesc') {
skuDescFirstLineBlue(iframeDocument);
}
// 获取对应的颜色映射
const colorMap = colorMaps[activateElementId];
const colorMap2 = colorMaps2[activateElementId];
const colorMap3 = colorMaps3[activateElementId];
if (colorMap) {
if (activateElementId === 'inventory') {
handleInventoryStyles(iframeDocument);
} else if (activateElementId === 'preSetInventory') {
handlePreSetInventoryStyles(iframeDocument);
}
else {
addNewStyles(iframeDocument, colorMap);
addNewStyles(iframeDocument, colorMap2);
addNewStyles(iframeDocument, colorMap3);
}
} else {
console.error('未找到对应的颜色映射。');
}
removeDataProcessed(iframeDocument);
isMarioShow.push(activateElementId);
}
} else {
console.error('无法访问iframe文档。');
}
} else {
console.error('未找到iframe元素。');
}
} else {
console.error('未找到激活元素。');
}
};
const removeDataProcessed = doc => {
const replaceElements = doc.querySelectorAll('[data-replace="true"]');
replaceElements.forEach(element => {
const parentElement = element.parentElement;
if (parentElement.tagName.toLowerCase() === 'p') {
// 检查 <p> 标签是否只有一个子元素,并且是当前的 <span>
const hasOnlySpanChild = parentElement.children.length === 1 && parentElement.children[0] === element;
// 获取父 <p> 元素的纯文本内容(不包括子元素)
const parentText = parentElement.textContent.trim();
if (hasOnlySpanChild && parentText === '无效内容') {
// 如果 <p> 标签没有其他文本内容,移除整个 <p> 标签
parentElement.remove();
} else {
// 否则,清空 <span> 的文本内容
element.textContent = '';
}
} else {
// 如果父元素不是 <p>,清空 <span> 的文本内容
element.textContent = '';
}
});
};
// 规格首行非sku描述行蓝色
const skuDescFirstLineBlue = doc => {
const firstPTag = doc.querySelector('#tinymce p');
if (firstPTag) {
if (!check_skuDescFirstLine.test(firstPTag.textContent)) {
applyColor(firstPTag, colorLibrary.blue);
}
const spanTags = firstPTag.querySelectorAll('span');
spanTags.forEach(spanTag => {
if (!check_skuDescFirstLine.test(firstPTag.textContent)) {
applyColor(spanTag, colorLibrary.blue);
}
});
}
};
// 到手价数字行红色
const modifyFirstPTagAndSpans = doc => {
const firstPTag = doc.querySelector('#tinymce p');
if (firstPTag) {
if (numericRegex.test(firstPTag.textContent)) {
applyColor(firstPTag, colorLibrary.red);
}
const spanTags = firstPTag.querySelectorAll('span');
spanTags.forEach(spanTag => {
if (numericRegex.test(spanTag.textContent)) {
applyColor(spanTag, colorLibrary.red);
}
});
}
};
// 预设库存样式修改
const handlePreSetInventoryStyles = doc => {
function check_content(content) {
return (!numericRegex.test(content) || content.includes('不可控'))
}
const pTags = doc.querySelectorAll('#tinymce p');
pTags.forEach(pTag => {
if (!numericRegex.test(pTag.textContent)) {
pTag.textContent = '拉满';
const spanTags = pTag.querySelectorAll('span');
spanTags.forEach(spanTag => {
if (check_content(spanTag.textContent)) {
spanTag.textContent = '拉满';
}
});
}
});
};
// 现货库存样式修改
const handleInventoryStyles = doc => {
let firstPTagFound = false;
const pTags = doc.querySelectorAll('#tinymce p');
pTags.forEach(pTag => {
// 获取 <p> 标签内的所有文本内容,并将连续的 转换为 <br>
let content = pTag.innerHTML.replace(/( )+/g, '<span data-replace="true">无效内容</span><br>');
// 获取 <p> 标签内的所有文本内容,并按 <br> 标签分割成数组
const segments = content.split('<br>');
// 处理每个分割后的段落
segments.forEach((segment, index) => {
// 创建临时容器元素以便于操作 HTML 字符串
const tempContainer = document.createElement('div');
tempContainer.innerHTML = segment;
// 获取段落的纯文本内容
const segmentText = tempContainer.textContent;
if (!firstPTagFound && segmentText.includes('预售')) {
firstPTagFound = true;
}
// 创建新的 <p> 标签用于包裹分隔后的段落
const newPTag = document.createElement('p');
newPTag.innerHTML = segment;
if (numericRegex.test(segmentText) || segmentText.includes('--')) {
applyColor(newPTag, colorMaps.inventory.default);
} else {
if (firstPTagFound) {
applyColor(newPTag, colorMaps.inventory.color2);
} else {
applyColor(newPTag, colorMaps.inventory.color1);
}
}
// 在原 <p> 标签位置插入新的 <p> 标签
pTag.parentNode.insertBefore(newPTag, pTag);
});
// 移除原始的 <p> 标签
pTag.parentNode.removeChild(pTag);
});
};
function autoWriteAvgPrice(iframeDocument) {
const ps = iframeDocument.querySelectorAll('p');
// 更新检测输入格式的正则表达式,支持小数
const pattern = /^\d+(\.\d+)?(\/\d+(\.\d+)?[^\d/\*]+)([/\*]\d+(\.\d+)?[^\d/\*]+)*$/;
ps.forEach(p => {
if (p.querySelector('span')) {
// 情况 1: p 标签内有 span 标签,需要处理 span 内的文本
processSpans(p, pattern);
} else {
// 情况 2: 只有 p 标签,没有嵌套的 span 标签
let newInnerHTML = '';
// 分割HTML内容
const parts = p.innerHTML.split(/(<br>| )/);
parts.forEach(part => {
let styledPart = part;
// console.log("styledPart:" + styledPart);
// 检查part是否符合格式
if (pattern.test(part)) {
// 调用parseInput来解析part并生成新内容
const { price, num, units } = parseInput(part);
styledPart = generateOutput(price, num, units);
}
newInnerHTML += styledPart;
// console.log("newInnerHTML:" + newInnerHTML);
});
// 更新p元素的内容
p.innerHTML = newInnerHTML;
}
});
function processSpans(element, pattern) {
const spans = element.querySelectorAll('span');
spans.forEach(span => {
const textContent = span.textContent;
// 检查textContent是否符合格式
if (pattern.test(textContent)) {
// 调用parseInput来解析textContent并生成新内容
const { price, num, units } = parseInput(textContent);
const newContent = generateOutput(price, num, units);
// 更新span的内容
span.innerHTML = newContent;
}
});
}
}
// 定义parseInput函数,用于解析输入
function parseInput(input) {
const pattern = /^\d+(\.\d+)?(\/\d+(\.\d+)?[^\d/\*]+)([/\*]\d+(\.\d+)?[^\d/\*]+)*$/;
if (!pattern.test(input)) {
throw new Error("输入格式不正确");
}
const priceMatch = input.match(/^\d+(\.\d+)?/);
const price = priceMatch ? parseFloat(priceMatch[0]) : null;
let rex = [];
let num = [];
let units = [];
const matches = input.match(/([/\*])(\d+(\.\d+)?)([^\d/\*]+)/g);
if (matches) {
matches.forEach((match, index) => {
const [, symbol, number, , unit] = match.match(/([/\*])(\d+(\.\d+)?)([^\d/\*]+)/);
rex.push(symbol);
let quantity = parseFloat(number);
if (symbol === "*" && index > 0) {
quantity *= num[num.length - 1];
}
num.push(quantity);
units.push(unit.trim());
});
}
return { price, rex, num, units };
}
// 定义generateOutput函数,用于生成输出内容
function generateOutput(price, num, units) {
let output = `<span>到手共${num[0]}${units[0]}</span><br>`;
for (let i = 0; i < num.length; i++) {
let avgPrice = (price / num[i]).toFixed(2).replace(/\.?0+$/, ""); // 计算结果并去掉末尾多余的零
output += `<span>平均每${units[i]}${avgPrice}</span><br>`;
if (i < num.length - 1) {
output += `<span>到手共${num[i + 1]}${units[i + 1]}</span><br>`;
}
}
// 去除末尾多余的 <br>
output = output.replace(/<br>$/, "");
return output;
}
/*
计算器功能区
*/
const calculate = [
{
regex: /折扣力度.*?(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/,
replaceFunc: (text, result) => {
// 替换文本中的折扣内容
let updatedText = text.replace(/(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/, `${result}`);
// 确保结果前有一个“约”字,并且前面有“:”或“:”
if (!updatedText.includes('约')) {
// 检查是否已有“:”或“:”,防止重复添加
if (!updatedText.includes(':') && !updatedText.includes(':')) {
updatedText = updatedText.replace(/(折扣力度.*?)(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/, `$1:约${result}`);
} else {
updatedText = updatedText.replace(/(折扣力度.*?)(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/, `$1约${result}`);
}
} else {
updatedText = updatedText.replace(/(:约|:约)?(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/, `:约${result}`);
}
// 确保结果后面有一个“折”字
if (!updatedText.endsWith('折')) {
updatedText += '折';
}
return updatedText;
},
decimalPlaces: 1,
multiplier: 10,
trimTrailingZeros: true
},
// {
// regex: /平均.*?(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/,
// replaceFunc: (text, result) => text.replace(/(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/, `${result}`),
// decimalPlaces: 2,
// multiplier: 1,
// trimTrailingZeros: true
// },
// {
// regex: /到手.*?(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/,
// replaceFunc: (text, result) => text.replace(/(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))/, `${result}`),
// decimalPlaces: 2,
// multiplier: 1,
// trimTrailingZeros: true
// },
{
regex: /.*?(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))==/,
replaceFunc: (text, result) => text.replace(/(\d+[\d+\-*/().]*\d*|\([\d+\-*/().]+\))==/, `${result}`),
decimalPlaces: 2,
multiplier: 1,
trimTrailingZeros: true
},
];
// 计算表达式的函数
const calculateExpression = (expression, decimalPlaces = 2, multiplier = 1, trimTrailingZeros = false) => {
try {
let result = eval(expression); // 注意:eval() 存在安全性问题,确保传入的表达式是安全的。
result = result * multiplier; // 放大结果
let formattedResult = result.toFixed(decimalPlaces); // 保留指定的小数位数
// 根据参数决定是否去除末尾的零
if (trimTrailingZeros) {
formattedResult = parseFloat(formattedResult).toString();
}
return formattedResult;
} catch (e) {
console.error('表达式计算错误:', e);
return expression; // 如果计算错误,返回原表达式
}
};
const findAndCalculateExpressions = (iframeDocument, calculate) => {
const discountElements = iframeDocument.querySelectorAll('p, span');
discountElements.forEach(element => {
let text = element.textContent.replace(/。/g, '.'); // 替换所有中文小数点为英文小数点
text = text.replace(/(/g, '(').replace(/)/g, ')'); // 替换中文括号为英文括号
calculate.forEach(({ regex, replaceFunc, decimalPlaces, multiplier, trimTrailingZeros }) => {
const match = text.match(regex);
console.log(match);
if (match) {
const expression = match[1];
// 检查是否为“折扣力度”的正则表达式
if (regex.source.includes('折扣力度')) {
if (/[+\-*/()]/.test(expression)) {
// 如果表达式包含运算符,进行计算
const result = calculateExpression(expression, decimalPlaces, multiplier, trimTrailingZeros);
text = replaceFunc(text, result);
} else {
// 如果表达式不包含运算符,直接使用替换函数处理
text = replaceFunc(text, expression);
}
} else {
// 其他情况照常处理
// 检查表达式是否包含运算符
if (/[+\-*/()]/.test(expression)) {
const result = calculateExpression(expression, decimalPlaces, multiplier, trimTrailingZeros);
text = replaceFunc(text, result);
}
}
element.textContent = text;
}
});
});
};
// 新增控制功能
// 支持单个元素内容的着色
// 封装函数返回包含SVG图标的div
function createMarioSVGIconWrapper(id) {
// 创建一个 div 容器
var divWrapper = document.createElement('div');
divWrapper.className = 'svg-icon-wrapper'; // 添加一个类名,便于查找和样式控制
divWrapper.style.cssText = 'display: flex; align-items: center; cursor: pointer; display: none;'; // 样式控制';
// 设置 div 的 id
if (id) {
divWrapper.id = id;
}
// 创建 SVG 图标
var svgIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgIcon.setAttribute('class', 'icon custom-mario-svg'); // 添加自定义类名
svgIcon.setAttribute('viewBox', '0 0 1024 1024');
svgIcon.setAttribute('width', '14');
svgIcon.setAttribute('height', '14');
svgIcon.innerHTML = '<path d="M288.581818 111.709091h55.854546v55.854545H288.581818V111.709091zM176.872727 595.781818h167.563637v55.854546H176.872727v-55.854546zM623.709091 502.690909h111.709091v55.854546h-111.709091v-55.854546zM679.563636 558.545455h111.709091v55.854545h-111.709091v-55.854545zM679.563636 614.4h167.563637v37.236364h-167.563637v-37.236364z" fill="#B8332B" p-id="3610"></path><path d="M176.872727 651.636364h167.563637v74.472727H176.872727v-74.472727zM176.872727 726.109091h111.709091v74.472727H176.872727v-74.472727zM735.418182 726.109091h111.709091v74.472727h-111.709091v-74.472727zM679.563636 651.636364h167.563637v74.472727h-167.563637v-74.472727zM363.054545 558.545455h55.854546v55.854545h-55.854546v-55.854545zM567.854545 558.545455h55.854546v55.854545h-55.854546v-55.854545z" fill="#FFF1E3" p-id="3611"></path><path d="M791.272727 595.781818h55.854546v18.618182h-55.854546v-18.618182zM735.418182 539.927273h37.236363v18.618182h-37.236363v-18.618182zM418.909091 446.836364h204.8v111.709091H418.909091v-111.709091zM232.727273 558.545455h111.709091v37.236363H232.727273v-37.236363zM344.436364 446.836364h18.618181v37.236363h-18.618181v-37.236363zM307.2 484.072727h55.854545v18.618182h-55.854545v-18.618182zM288.581818 502.690909h74.472727v37.236364H288.581818v-37.236364zM251.345455 539.927273h111.70909v18.618182H251.345455v-18.618182zM623.709091 111.709091h18.618182v55.854545h-18.618182V111.709091zM642.327273 148.945455h148.945454v18.618181h-148.945454V148.945455zM344.436364 93.090909h279.272727v74.472727H344.436364V93.090909z" fill="#B8332B" p-id="3612"></path><path d="M344.436364 55.854545h279.272727v37.236364H344.436364V55.854545zM642.327273 111.709091h148.945454v37.236364h-148.945454V111.709091zM288.581818 446.836364h55.854546v37.236363H288.581818v-37.236363zM735.418182 502.690909h55.854545v37.236364h-55.854545v-37.236364zM791.272727 558.545455h55.854546v37.236363h-55.854546v-37.236363zM288.581818 484.072727h18.618182v18.618182H288.581818v-18.618182zM772.654545 539.927273h18.618182v18.618182h-18.618182v-18.618182zM232.727273 539.927273h18.618182v18.618182H232.727273v-18.618182zM232.727273 502.690909h55.854545v37.236364H232.727273v-37.236364zM176.872727 558.545455h55.854546v37.236363H176.872727v-37.236363z" fill="#FF655B" p-id="3613"></path><path d="M288.581818 167.563636h55.854546v55.854546H288.581818V167.563636zM288.581818 335.127273h55.854546v55.854545H288.581818v-55.854545z" fill="#432E23" p-id="3614"></path><path d="M269.963636 856.436364h148.945455v55.854545H269.963636v-55.854545zM269.963636 912.290909h148.945455v55.854546H269.963636v-55.854546z" fill="#9F5A31" p-id="3615"></path><path d="M176.872727 912.290909h93.090909v37.236364H176.872727v-37.236364zM754.036364 912.290909h93.090909v37.236364h-93.090909v-37.236364z" fill="#F38C50" p-id="3616"></path><path d="M176.872727 949.527273h93.090909v18.618182H176.872727v-18.618182zM754.036364 949.527273h93.090909v18.618182h-93.090909v-18.618182zM605.090909 856.436364h148.945455v55.854545h-148.945455v-55.854545zM605.090909 912.290909h148.945455v55.854546h-148.945455v-55.854546z" fill="#9F5A31" p-id="3617"></path><path d="M363.054545 446.836364h55.854546v111.709091h-55.854546v-111.709091zM363.054545 614.4h316.509091v37.236364H363.054545v-37.236364zM344.436364 651.636364h335.127272v74.472727H344.436364v-74.472727zM288.581818 726.109091h446.836364v74.472727H288.581818v-74.472727zM418.909091 595.781818h148.945454v18.618182h-148.945454v-18.618182zM288.581818 800.581818h167.563637v55.854546H288.581818v-55.854546zM567.854545 800.581818h167.563637v55.854546h-167.563637v-55.854546zM623.709091 558.545455h55.854545v55.854545h-55.854545v-55.854545z" fill="#2E67B1" p-id="3618"></path><path d="M418.909091 558.545455h148.945454v37.236363h-148.945454v-37.236363z" fill="#66A8FF" p-id="3619"></path><path d="M344.436364 558.545455h18.618181v93.090909h-18.618181v-93.090909z" fill="#2E67B1" p-id="3620"></path><path d="M400.290909 279.272727h55.854546v55.854546h-55.854546v-55.854546zM400.290909 167.563636h55.854546v55.854546h-55.854546V167.563636zM344.436364 167.563636h55.854545v167.563637h-55.854545V167.563636zM623.709091 279.272727h55.854545v55.854546h-55.854545v-55.854546zM567.854545 223.418182h55.854546v55.854545h-55.854546v-55.854545zM567.854545 335.127273h223.418182v55.854545H567.854545v-55.854545z" fill="#432E23" p-id="3621"></path><path d="M288.581818 223.418182h55.854546v111.709091H288.581818v-111.709091zM456.145455 167.563636h223.418181v55.854546H456.145455V167.563636zM400.290909 223.418182h167.563636v55.854545h-167.563636v-55.854545zM456.145455 279.272727h167.563636v55.854546h-167.563636v-55.854546zM344.436364 335.127273h223.418181v55.854545H344.436364v-55.854545zM344.436364 390.981818h390.981818v55.854546H344.436364v-55.854546zM623.709091 223.418182h167.563636v55.854545h-167.563636v-55.854545zM679.563636 279.272727h167.563637v55.854546h-167.563637v-55.854546z" fill="#FFF1E3" p-id="3622"></path><path d="M232.727273 223.418182h55.854545v167.563636H232.727273v-167.563636z" fill="#432E23" p-id="3623"></path><path d="M232.727273 111.709091h55.854545v111.709091H232.727273V111.709091zM176.872727 223.418182h55.854546v167.563636H176.872727v-167.563636zM232.727273 390.981818h111.709091v55.854546H232.727273v-55.854546zM176.872727 800.581818h111.709091v55.854546H176.872727v-55.854546zM456.145455 800.581818h111.70909v55.854546h-111.70909v-55.854546zM176.872727 856.436364h93.090909v55.854545H176.872727v-55.854545zM121.018182 912.290909h55.854545v111.709091H121.018182v-111.709091zM847.127273 912.290909h55.854545v111.709091h-55.854545v-111.709091zM176.872727 968.145455h223.418182v55.854545H176.872727v-55.854545zM623.709091 968.145455h223.418182v55.854545H623.709091v-55.854545zM735.418182 800.581818h111.709091v55.854546h-111.709091v-55.854546zM754.036364 856.436364h93.090909v55.854545h-93.090909v-55.854545zM288.581818 55.854545h55.854546v55.854546H288.581818V55.854545zM232.727273 446.836364h55.854545v55.854545H232.727273v-55.854545zM176.872727 502.690909h55.854546v55.854546H176.872727v-55.854546zM791.272727 502.690909h55.854546v55.854546h-55.854546v-55.854546zM121.018182 558.545455h55.854545v242.036363H121.018182V558.545455zM418.909091 856.436364h55.854545v111.709091h-55.854545v-111.709091zM549.236364 856.436364h55.854545v111.709091h-55.854545v-111.709091zM847.127273 558.545455h55.854545v242.036363h-55.854545V558.545455zM791.272727 111.709091h55.854546v55.854545h-55.854546V111.709091zM791.272727 223.418182h55.854546v55.854545h-55.854546v-55.854545zM847.127273 279.272727h55.854545v55.854546h-55.854545v-55.854546zM791.272727 335.127273h55.854546v55.854545h-55.854546v-55.854545zM735.418182 390.981818h55.854545v55.854546h-55.854545v-55.854546zM623.709091 446.836364h167.563636v55.854545h-167.563636v-55.854545zM623.709091 55.854545h167.563636v55.854546h-167.563636V55.854545zM679.563636 167.563636h111.709091v55.854546h-111.709091V167.563636zM344.436364 0h279.272727v55.854545H344.436364V0z" fill="#10001D" p-id="3624"></path>';
svgIcon.style.cssText = 'vertical-align: middle;'; // 垂直居中样式
// 将 SVG 添加到 div 容器中
divWrapper.appendChild(svgIcon);
// 根据 id 绑定点击事件
divWrapper.addEventListener('click', function () {
// 提取 id 中的 suffix 部分
var idSuffix = id.replace('svg-icon-', '');
// 根据 id 调用对应的函数
switch (id) {
case 'svg-icon-skuDesc':
activateIframeAndModifyStyles('skuDesc');
break;
case 'svg-icon-livePrice':
activateIframeAndModifyStyles('livePrice');
break;
case 'svg-icon-liveGameplay':
activateIframeAndModifyStyles('liveGameplay');
break;
case 'svg-icon-preSetInventory':
activateIframeAndModifyStyles('preSetInventory');
break;
case 'svg-icon-inventory':
activateIframeAndModifyStyles('inventory');
break;
default:
break;
}
// 仅当 idSuffix 不在数组中时才添加
if (!isMarioShow.includes(idSuffix)) {
isMarioShow.push(idSuffix);
}
});
return divWrapper;
}
// 查找表格中的目标单元格并添加SVG图标
function addSVGToSpecificTDs() {
// 获取 class="card-content-container" 内的表格
var container = document.querySelector('.card-content-container');
if (!container) return;
var table = container.querySelector('table');
if (!table) return;
var tbody = table.querySelector('tbody');
if (!tbody) return;
// 获取 tbody 内的第二个 tr
var secondTR = tbody.querySelectorAll('tr')[1]; // 获取第二个 tr
if (!secondTR) return;
// 获取第二个 tr 中的所有 td
var tds = secondTR.querySelectorAll('td');
var idMap = {
"规格": "svg-icon-skuDesc",
"直播间到手价": "svg-icon-livePrice",
"优惠方式": "svg-icon-liveGameplay",
"预设库存": "svg-icon-preSetInventory",
"现货库存": "svg-icon-inventory"
}; // 文本内容与ID的映射
tds.forEach(function (td) {
// 检查 td 的文本内容是否在目标文本内容列表中
var span = td.querySelector('.link-node-container > span');
if (span && idMap.hasOwnProperty(span.textContent.trim())) {
// 检查是否已经存在封装的 SVG 图标,避免重复添加
if (!td.querySelector('.svg-icon-wrapper')) {
// 获取对应的 id
var id = idMap[span.textContent.trim()];
// 创建包含 SVG 图标的 div 容器并设置 id
var svgWrapper = createMarioSVGIconWrapper(id);
// 将 SVG 容器插入到 span 之后
span.parentNode.insertAdjacentElement('afterend', svgWrapper);
}
}
});
}
// 初始化存储被点击事件的数组
var isMarioShow = [];
// 函数:控制每个 divWrapper 的显示状态
function updateDivWrapperDisplay(isShow) {
// 获取所有 class 为 'svg-icon-wrapper' 的元素
const divWrappers = document.querySelectorAll('.svg-icon-wrapper');
// 遍历所有 divWrapper
for (const divWrapper of divWrappers) {
if (isShow) {
divWrapper.style.display = 'flex';
} else {
// 获取该 divWrapper 的 id
var wrapperId = divWrapper.id;
// 检查是否存在于 isMarioShow 数组中
if (isMarioShow.includes(wrapperId.replace('svg-icon-', ''))) {
divWrapper.style.display = 'flex';
} else {
divWrapper.style.display = 'none';
}
}
}
}
/*
淘宝、天猫主图复制到剪贴板功能
*/
function createGetTmallPngButton() {
// 找到匹配的元素的编号
function findMatchingIndex(wrapperClass, imgClass) {
for (let i = 0; i < wrapperClass.length; i++) {
const wrapper = document.querySelector(wrapperClass[i]);
if (wrapper) {
const img = wrapper.querySelector(imgClass[i]);
if (img) {
return i; // 返回匹配的编号
}
}
}
return -1; // 如果没有找到匹配的元素,则返回 -1
}
if (!document.querySelector('#button_getTmallPngButton')) {
const wrapperClass = ['.PicGallery--mainPicWrap--juPDFPo', '.PicGallery--mainPicWrap--1c9k21r','.item-gallery-top.item-gallery-prepub2'];
const imgClass = ['.PicGallery--mainPic--34u4Jrw', '.PicGallery--mainPic--1eAqOie','.item-gallery-top__img'];
const matchingIndex = findMatchingIndex(wrapperClass, imgClass);
if (matchingIndex !== -1) {
const wrapper = document.querySelector(wrapperClass[matchingIndex]);
console.log("wrapper:", wrapper);
if (wrapper) {
const button = document.createElement('button');
button.textContent = '复制图片';
button.id = 'button_getTmallPngButton';
button.style.cssText = `
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 5px 20px;
font-size: 16px;
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
border: none;
border-radius: 999px;
font-family: AlibabaPuHuiTi_2_55_Regular;
backdrop-filter: blur(10px) brightness(90%); /* 添加模糊效果 */
-webkit-backdrop-filter: blur(10px); /* 兼容Safari浏览器 */
text-align: center; /* 文本居中显示 */
cursor: pointer;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 999;
`;
// 控制按钮显示
wrapper.addEventListener('mouseenter', () => {
button.style.opacity = '1';
});
// 控制按钮隐藏
wrapper.addEventListener('mouseleave', () => {
button.style.opacity = '0';
});
button.addEventListener('click', async () => {
const img = wrapper.querySelector(imgClass[matchingIndex]);
console.log("img:", img);
if (img) {
try {
const imageUrl = img.src;
const response = await fetch(imageUrl);
const blob = await response.blob();
const image = new Image();
image.src = URL.createObjectURL(blob);
image.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
canvas.toBlob(async (blob) => {
try {
await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]);
showNotification("图片已成功复制到剪贴板", undefined, true);
// alert('Image copied to clipboard!');
} catch (error) {
console.error('Failed to copy image to clipboard:', error);
// alert('Failed to copy image to clipboard.');
showNotification('图片复制失败!');
}
}, 'image/png');
};
} catch (error) {
showNotification('图片复制失败!');
console.error('Failed to fetch or process image:', error);
// alert('Failed to copy image to clipboard.');
}
} else {
// alert('Image not found!');
}
});
wrapper.style.position = 'relative'; // 确保按钮在图片上层
wrapper.appendChild(button);
} else {
// console.error('Wrapper element not found.');
}
} else {
// console.error('No matching element found.');
}
} else {
// console.log('Button already exists, skipping creation.');
}
}
})();