// ==UserScript==
// @name 闲鱼管家上货助手
// @namespace http://tampermonkey.net/
// @version 1.13
// @description 在商品页面复制商品信息并在闲鱼管家后台上架页面插入“一键填充”按钮,添加下载商品详情图片的功能。
// @author 阿阅 wx:pangyue2 mail:[email protected]
// @match https://h5.m.goofish.com/item?id=*
// @match https://www.goofish.pro/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=goofish.pro
// @grant GM_setValue
// @grant GM_getValue
// @require https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
// @license MIT
// ==/UserScript==
(function() {
'use strict';
function showToast(message, type = 'success') {
Swal.fire({
toast: true,
position: 'top-end',
icon: type,
title: message,
showConfirmButton: false,
timer: 1500
});
}
function downloadImage(url, fileName) {
fetch(url)
.then(response => response.blob())
.then(blob => {
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = `${fileName}.jpg`;
a.click();
URL.revokeObjectURL(a.href);
})
.catch(error => console.error('图片下载失败:', error));
}
// 生成随机数
function getRandomNumber(min, max) {
const randomInt = Math.floor(Math.random() * ((max / 10) - (min / 10) + 1)) + (min / 10);
return randomInt * 10;
}
// 获取价格,适配不同格式,比如 1~10、10
function getPrice(priceStr) {
// 移除特殊字符 "¥" 和 "\n"
const cleanedStr = priceStr.replace(/[¥\n]/g, '');
// 使用正则表达式提取所有数字
const numbers = cleanedStr.match(/\d+(\.\d+)?/g);
if (numbers === null) {
return null; // 如果没有匹配到数字,返回null
}
// 将提取出的字符串数字转换为浮点数
const prices = numbers.map(Number);
// 找出最大值
const maxPrice = Math.max(...prices);
return maxPrice;
}
// 商品页面逻辑
if (window.location.href.includes('https://h5.m.goofish.com/item?id=')) {
document.querySelector('.Detail--qrcodeContainer--390dBY_').remove()
if (window.top === window.self) {
setTimeout(() => {
const button = document.createElement('button');
const iframe = document.querySelector('iframe');
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
const goofishImages = iframeDocument.querySelectorAll('img[quality="normal"]');
button.innerHTML = `复制商品信息 & 下载图片( <b> ${goofishImages.length} </b>)`;
button.style.position = 'fixed';
button.style.bottom = '20px';
button.style.left = '20px';
button.style.zIndex = 1000;
button.style.padding = '10px 20px';
button.style.backgroundColor = '#28a745';
button.style.color = 'white';
button.style.border = 'none';
button.style.borderRadius = '5px';
button.style.cursor = 'pointer';
document.body.appendChild(button);
button.addEventListener('click', () => {
copyGoods()
downloadImages()
});
}, 1500)
// 复制商品信息
function copyGoods() {
const iframe = document.querySelector('iframe');
if (iframe) {
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
const detailTextElements = iframeDocument.querySelectorAll('.detailDesc--descText--1FMDTCm');
const priceElements = iframeDocument.querySelectorAll('.priceMod--priceTextWrap--3PwMboh');
if (detailTextElements.length > 0 && priceElements.length > 0) {
const detailText = detailTextElements[0].innerText;
const indexOfFirstNewLine = detailText.indexOf('\n');
let productName, productDescription;
if (indexOfFirstNewLine !== -1) {
productName = detailText.slice(0, indexOfFirstNewLine).trim();
productDescription = detailText.trim();
const goodsId = new URL(location.href).searchParams.get('id');
productDescription +=`\n \n[钉子]发的是百 度 网 盘 链 接,永不失效,售出不退。
[钉子]任何情况,不要申请退款,私信沟通给你处理,小店经营不易。
[钉子]所有文件均获取自网络公开渠道,仅供学习和交流使用,所有版权归版权人所有,如版权方认为侵犯了您的版权,请及时联系小店删除。`
productDescription += `\n${goodsId}`;
} else {
productName = detailText.trim();
productDescription = '';
}
// 裁剪商品标题到30个中文字以内
const maxTitleLength = 30;
productName = productName.slice(0, maxTitleLength);
const productPrice = getPrice(priceElements[0].innerText.trim());
GM_setValue('productName', productName);
GM_setValue('productDescription', productDescription);
GM_setValue('productPrice', productPrice);
console.log('商品信息已存储');
console.log('商品名:', productName);
console.log('商品详情:', productDescription);
console.log('商品价格:', productPrice);
showToast('商品信息已复制');
} else {
console.error('未找到商品详情或价格元素');
showToast('未找到商品详情或价格元素', 'error');
}
} else {
console.error('未找到iframe');
showToast('未找到iframe', 'error');
}
}
// 下载商品图片
function downloadImages () {
const iframe = document.querySelector('iframe');
if (iframe) {
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
const detailTextElements = iframeDocument.querySelectorAll('.detailDesc--descText--1FMDTCm');
let productName = '';
if (detailTextElements.length > 0) {
const detailText = detailTextElements[0].innerText;
const indexOfFirstNewLine = detailText.indexOf('\n');
if (indexOfFirstNewLine !== -1) {
productName = detailText.slice(0, indexOfFirstNewLine).trim();
} else {
productName = detailText.trim();
}
const goofishImages = iframeDocument.querySelectorAll('img[quality="normal"]');
goofishImages.forEach((img, index) => {
setTimeout(() => {
let src = img.src.replace(/_webp$/, ''); // 去掉_webp并下载jpg格式
downloadImage(src, `${index + 1}`);
}, index * 100); // 每个下载任务之间延迟100毫秒
});
showToast('图片下载开始');
} else {
console.error('未能找到商品描述文本元素');
showToast('未能找到商品描述文本元素', 'error');
}
} else {
console.error('未找到iframe元素');
showToast('未找到iframe元素', 'error');
}
}
}
}
// 闲鱼管家上架页面逻辑
if (window.location.href.includes('https://www.goofish.pro')) {
const button = document.createElement('button');
button.innerText = '一键填充';
button.style.position = 'fixed';
button.style.bottom = '10px';
button.style.left = '150px';
button.style.zIndex = 1000;
button.style.padding = '10px 20px';
button.style.backgroundColor = '#28a745';
button.style.color = 'white';
button.style.border = 'none';
button.style.borderRadius = '5px';
button.style.cursor = 'pointer';
document.body.appendChild(button);
button.addEventListener('click', () => {
// 检查当前页面是否是商品添加页面
if (!window.location.href.includes('/sale/product/add')) {
window.location.href = 'https://www.goofish.pro/sale/product/add?from=%2Fon-sale';
setTimeout(() => fillProductInfo(), 1500);
return;
} else {
fillProductInfo();
}
});
}
function fillProductInfo() {
// 从 Tampermonkey 存储中获取商品信息
const productName = GM_getValue('productName', '');
const productDescription = GM_getValue('productDescription', '') || productName;
let prict = GM_getValue('productPrice')
let productPrice = 100
if (prict < 2) {
productPrice = 1.9
} else {
productPrice = parseFloat(GM_getValue('productPrice', '100')) - 0.1;
}
if (!productName || !productDescription || isNaN(productPrice)) {
showToast('请先去闲鱼详情页复制商品信息', 'warning');
return;
}
console.log('读取到的商品名:', productName);
console.log('读取到的商品详情:', productDescription);
console.log('读取到的商品价格:', productPrice);
// 选择类目
const categoryElements = document.querySelectorAll('.release-history');
if (categoryElements.length > 0) {
categoryElements[0].click();
} else {
console.error('未找到类目选择元素');
showToast('未找到类目选择元素', 'error');
}
setTimeout(() => {
// 选择店铺
const shopList = document.querySelectorAll('ul.auth-list li');
if (shopList.length > 0) {
shopList[0].click();
} else {
console.error('未找到目标店铺元素');
showToast('未找到目标店铺元素', 'error');
}
setTimeout(() => {
// 填充商品名
const inputElements = document.querySelectorAll('.el-input__inner');
if (inputElements.length > 2) {
inputElements[2].value = productName;
const event = new Event('input', { bubbles: true });
inputElements[2].dispatchEvent(event);
} else {
console.error('未找到商品标题输入框');
showToast('未找到商品标题输入框', 'error');
}
// 填充商品详情
const descriptionElements = document.querySelectorAll('.el-textarea__inner');
if (descriptionElements.length > 0) {
descriptionElements[0].value = productDescription;
const event = new Event('input', { bubbles: true });
descriptionElements[0].dispatchEvent(event);
} else {
console.error('未找到商品描述输入框');
showToast('未找到商品描述输入框', 'error');
}
// 填充价格
if (inputElements.length > 4) {
inputElements[4].value = productPrice.toFixed(2);
const event = new Event('input', { bubbles: true });
inputElements[4].dispatchEvent(event);
} else {
console.error('未找到价格输入框');
showToast('未找到价格输入框', 'error');
}
// 填充原价
if (inputElements.length > 5) {
inputElements[5].value = getRandomNumber(200, 500);
const event = new Event('input', { bubbles: true });
inputElements[5].dispatchEvent(event);
} else {
console.error('未找到价格输入框');
showToast('未找到价格输入框', 'error');
}
// 填充库存
const productStore = 100
if (inputElements.length > 5) {
inputElements[6].value = productStore;
const event = new Event('input', { bubbles: true });
inputElements[6].dispatchEvent(event);
} else {
console.error('未找到库存输入框');
showToast('未找到库存输入框', 'error');
}
// 选择发布商品时机
const radioElements = document.querySelectorAll('.el-radio');
if (radioElements.length > 11) {
radioElements[11].click();
} else {
console.error('未找到发布商品时机的单选框');
showToast('未找到发布商品时机的单选框', 'error');
}
showToast('商品信息已填充');
}, 500);
}, 500);
}
// 闲鱼详情页:提取并显示想要人数、浏览量和转化率
if (window.location.href.includes('https://h5.m.goofish.com/item?id=')) {
// 等待 iframe 加载完成
window.addEventListener('load', function() {
setTimeout(() => {
const iframe = document.querySelector('iframe');
if (iframe) {
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
const spanElement = iframeDocument.querySelector('#root > div > div > div > div.rax-view-v2.normal--detailContainer--1YGYI4g > div > div.rax-view-v2.subDetailMod--wantDetailContainer--79Lt27G > div.rax-view-v2.subDetailMod--wantDetailWrap--3bi5Jov > span')
if (spanElement) {
const textContent = spanElement.textContent.trim();
const [wantText, , viewText] = textContent.split(' · ');
const wantNumber = parseInt(wantText.replace('人想要', '').trim(), 10);
const viewNumber = parseInt(viewText.replace('浏览', '').trim(), 10);
const conversionRate = (wantNumber / viewNumber * 100).toFixed(0);
const conversionRateText = conversionRate + '%';
const statsDiv = document.createElement('div');
statsDiv.style.position = 'fixed';
statsDiv.style.top = '10px';
statsDiv.style.left = '10px';
statsDiv.style.backgroundColor = 'gray';
statsDiv.style.color = 'white';
statsDiv.style.padding = '10px';
statsDiv.style.zIndex = '1000';
statsDiv.style.fontSize = '14px';
const conversionRateSpan = document.createElement('span');
conversionRateSpan.textContent = conversionRateText;
conversionRateSpan.style.backgroundColor = conversionRate > 7 ? 'green' : 'red';
conversionRateSpan.style.padding = '2px 4px';
statsDiv.innerHTML = `
想要数 : ${wantNumber}<br>
浏览量 : ${viewNumber}<br>
转化率 : `;
statsDiv.appendChild(conversionRateSpan);
document.body.appendChild(statsDiv);
if (conversionRate < 7) {
console.log(`转化率太低了 ${conversionRate}%`)
}
} else {
console.error('无法找到目标 span 元素');
}
} else {
console.error('无法找到 iframe 元素');
}
}, 500); // 延时以确保 iframe 内容已加载
});
}
})();