闲鱼管家上货助手

在商品页面复制商品信息并在闲鱼管家后台上架页面插入“一键填充”按钮,添加下载商品详情图片的功能。包括选品功能,可在闲鱼商详页导出猜你喜欢的数据到Excel,支持动态数据

  1. // ==UserScript==
  2. // @name 闲鱼管家上货助手
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.21
  5. // @description 在商品页面复制商品信息并在闲鱼管家后台上架页面插入“一键填充”按钮,添加下载商品详情图片的功能。包括选品功能,可在闲鱼商详页导出猜你喜欢的数据到Excel,支持动态数据
  6. // @author 阿阅 wx:pangyue2 mail:pang-yue@qq.com
  7. // @match https://h5.m.goofish.com/item?id=*
  8. // @match https://www.goofish.com/item*
  9. // @match https://goofish.pro/*
  10. // @match https://www.goofish.pro/*
  11. // @icon https://www.google.com/s2/favicons?sz=64&domain=goofish.pro
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // @require https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js
  15. // @require https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
  16. // @license MIT
  17. // ==/UserScript==
  18.  
  19. (function () {
  20. "use strict";
  21.  
  22. // 使用 unsafeWindow 访问原始 window 对象
  23. const unsafeWindow = window.unsafeWindow || window;
  24.  
  25. interceptRequests();
  26.  
  27. function showToast(message, type = "success") {
  28. Swal.fire({
  29. toast: true,
  30. position: "top-end",
  31. icon: type,
  32. title: message,
  33. showConfirmButton: false,
  34. timer: 1500,
  35. });
  36. }
  37.  
  38. function downloadImage(url, fileName) {
  39. fetch(url)
  40. .then((response) => response.blob())
  41. .then((blob) => {
  42. const a = document.createElement("a");
  43. a.href = URL.createObjectURL(blob);
  44. a.download = `${fileName}.jpg`;
  45. a.click();
  46. URL.revokeObjectURL(a.href);
  47. })
  48. .catch((error) => console.error("图片下载失败:", error));
  49. }
  50.  
  51. // 生成随机数
  52. function getRandomNumber(min, max) {
  53. const randomInt =
  54. Math.floor(Math.random() * (max / 10 - min / 10 + 1)) + min / 10;
  55. return randomInt * 10;
  56. }
  57.  
  58. // 获取价格,适配不同格式,比如 1~10、10
  59. function getPrice(priceStr) {
  60. // 移除特殊字符 "¥" 和 "\n"
  61. const cleanedStr = priceStr.replace(/[¥\n]/g, "");
  62.  
  63. // 使用正则表达式提取所有数字
  64. const numbers = cleanedStr.match(/\d+(\.\d+)?/g);
  65.  
  66. if (numbers === null) {
  67. return null; // 如果没有匹配到数字,返回null
  68. }
  69.  
  70. // 将提取出的字符串数字转换为浮点数
  71. const prices = numbers.map(Number);
  72.  
  73. // 找出最大值
  74. const maxPrice = Math.max(...prices);
  75.  
  76. return maxPrice;
  77. }
  78.  
  79. // 商品页面逻辑
  80. if (window.location.href.includes("https://www.goofish.com/item")) {
  81. setTimeout(() => {
  82. const button = document.createElement("button");
  83. let goofishImages = document.querySelectorAll(
  84. "div.slick-slide:not(.slick-cloned)"
  85. ).length;
  86.  
  87. button.innerHTML = `复制商品信息 & 下载图片( <b> ${goofishImages} </b>)`;
  88. button.style.position = "fixed";
  89. button.style.bottom = "20px";
  90. button.style.left = "20px";
  91. button.style.zIndex = 1000;
  92. button.style.padding = "10px 20px";
  93. button.style.backgroundColor = "#28a745";
  94. button.style.color = "white";
  95. button.style.border = "none";
  96. button.style.borderRadius = "5px";
  97. button.style.cursor = "pointer";
  98.  
  99. document.body.appendChild(button);
  100.  
  101. button.addEventListener("click", () => {
  102. copyGoods();
  103. downloadImages();
  104. });
  105. }, 1500);
  106.  
  107. // 复制商品信息
  108. function copyGoods() {
  109. const detailTextElements = document.querySelectorAll(".desc--WLgQcGKD");
  110. const priceElements = document.querySelectorAll(".price--Ls68DZ8a ");
  111. let index = 0
  112. if (detailTextElements.length > 1) index = 1 // 避免获取错元素
  113.  
  114. if (detailTextElements.length > 0 && priceElements.length > 0) {
  115. const detailText = detailTextElements[index].innerText;
  116. const indexOfFirstNewLine = detailText.indexOf(" ");
  117. let productName, productDescription;
  118.  
  119. if (indexOfFirstNewLine !== -1) {
  120. productName = detailText.slice(0, indexOfFirstNewLine).trim();
  121. productDescription = detailText.trim();
  122. } else {
  123. productName = detailText.trim();
  124. productDescription = "";
  125. }
  126.  
  127. // 裁剪商品标题到30个中文字以内
  128. const maxTitleLength = 30;
  129. productName = productName.slice(0, maxTitleLength);
  130.  
  131. const productPrice = getPrice(priceElements[0].innerText.trim());
  132.  
  133. GM_setValue("productName", productName);
  134. // GM_setValue("productDescription", productDescription);
  135. GM_setValue("productPrice", productPrice);
  136.  
  137. console.log("商品信息已存储");
  138. console.log("商品名:", productName);
  139. // console.log("商品详情:", productDescription);
  140. console.log("商品价格:", productPrice);
  141.  
  142. showToast("商品信息已复制");
  143. } else {
  144. console.error("未找到商品详情或价格元素");
  145. showToast("未找到商品详情或价格元素", "error");
  146. }
  147. }
  148.  
  149. // 下载商品图片
  150. function downloadImages() {
  151. // 获取所有 class 为 slick-slide 且不包含 slick-cloned 的 div 元素
  152. const goofishImageDivs = document.querySelectorAll(
  153. "div.slick-slide:not(.slick-cloned)"
  154. );
  155.  
  156. // 遍历这些 div 元素,获取其中的 img 标签
  157. const goofishImages = Array.from(goofishImageDivs).map((div) =>
  158. div.querySelector("img")
  159. );
  160.  
  161. // 过滤掉可能不存在 img 标签的 div
  162. const filteredGoofishImages = goofishImages.filter((img) => img !== null);
  163.  
  164. filteredGoofishImages.forEach((img, index) => {
  165. setTimeout(() => {
  166. let src = img.src.replace(/_webp$/, ""); // 去掉_webp并下载jpg格式
  167. downloadImage(src, `${index + 1}`);
  168. }, index * 100); // 每个下载任务之间延迟100毫秒
  169. });
  170. showToast("图片正在开始");
  171. }
  172. }
  173.  
  174. // 闲鱼管家上架页面逻辑
  175. if (window.location.hostname.includes("goofish.pro")) {
  176. const button = document.createElement("button");
  177. button.innerText = "一键填充";
  178. button.style.position = "fixed";
  179. button.style.bottom = "10px";
  180. button.style.left = "150px";
  181. button.style.zIndex = 1000;
  182. button.style.padding = "10px 20px";
  183. button.style.backgroundColor = "#28a745";
  184. button.style.color = "white";
  185. button.style.border = "none";
  186. button.style.borderRadius = "5px";
  187. button.style.cursor = "pointer";
  188.  
  189. document.body.appendChild(button);
  190.  
  191. button.addEventListener("click", () => {
  192. // 检查当前页面是否是商品添加页面
  193. if (!window.location.href.includes("/sale/product/add")) {
  194. window.location.href =
  195. "https://goofish.pro/sale/product/add?from=%2Fon-sale";
  196. setTimeout(() => fillProductInfo(), 1500);
  197. return;
  198. } else {
  199. fillProductInfo();
  200. }
  201. });
  202. }
  203.  
  204. function fillProductInfo() {
  205. // 从 Tampermonkey 存储中获取商品信息
  206. const productName = GM_getValue("productName", "");
  207. const productDescription = GM_getValue("productDescription", "") || productName;
  208. let prict = GM_getValue("productPrice");
  209. let productPrice = 100;
  210. if (prict < 2) {
  211. productPrice = 1.9;
  212. } else {
  213. productPrice = parseFloat(GM_getValue("productPrice", "100")) - 0.1;
  214. }
  215.  
  216. if (!productName || !productDescription || isNaN(productPrice)) {
  217. showToast("请先去闲鱼详情页复制商品信息", "warning");
  218. return;
  219. }
  220.  
  221. console.log("读取到的商品名:", productName);
  222. console.log("读取到的商品详情:", productDescription);
  223. console.log("读取到的商品价格:", productPrice);
  224.  
  225. // 选择类目
  226. const categoryElements = document.querySelectorAll(".release-history");
  227. if (categoryElements.length > 0) {
  228. categoryElements[0].click();
  229. } else {
  230. console.error("未找到类目选择元素");
  231. showToast("未找到类目选择元素", "error");
  232. }
  233.  
  234. setTimeout(() => {
  235. // 选择店铺
  236. const shopList = document.querySelectorAll("ul.auth-list li");
  237. if (shopList.length > 0) {
  238. shopList[0].click();
  239. } else {
  240. console.error("未找到目标店铺元素");
  241. showToast("未找到目标店铺元素", "error");
  242. }
  243.  
  244. setTimeout(() => {
  245. // 填充商品名
  246. const inputElements = document.querySelectorAll(".el-input__inner");
  247. if (inputElements.length > 2) {
  248. inputElements[2].value = productName;
  249. const event = new Event("input", { bubbles: true });
  250. inputElements[2].dispatchEvent(event);
  251. } else {
  252. console.error("未找到商品标题输入框");
  253. showToast("未找到商品标题输入框", "error");
  254. }
  255.  
  256. // 填充商品详情
  257. const descriptionElements = document.querySelectorAll(
  258. ".el-textarea__inner"
  259. );
  260. if (descriptionElements.length > 0) {
  261. descriptionElements[0].value = productDescription;
  262. const event = new Event("input", { bubbles: true });
  263. descriptionElements[0].dispatchEvent(event);
  264. } else {
  265. console.error("未找到商品描述输入框");
  266. showToast("未找到商品描述输入框", "error");
  267. }
  268.  
  269. // 填充价格
  270. if (inputElements.length > 4) {
  271. inputElements[4].value = productPrice.toFixed(2);
  272. const event = new Event("input", { bubbles: true });
  273. inputElements[4].dispatchEvent(event);
  274. } else {
  275. console.error("未找到价格输入框");
  276. showToast("未找到价格输入框", "error");
  277. }
  278.  
  279. // // 填充原价
  280. // if (inputElements.length > 5) {
  281. // inputElements[5].value = getRandomNumber(200, 500);
  282. // const event = new Event('input', { bubbles: true });
  283. // inputElements[5].dispatchEvent(event);
  284. // } else {
  285. // console.error('未找到价格输入框');
  286. // showToast('未找到价格输入框', 'error');
  287. // }
  288.  
  289. // 填充库存
  290. const productStore = 1;
  291. if (inputElements.length > 5) {
  292. inputElements[6].value = productStore;
  293. const event = new Event("input", { bubbles: true });
  294. inputElements[6].dispatchEvent(event);
  295. } else {
  296. console.error("未找到库存输入框");
  297. showToast("未找到库存输入框", "error");
  298. }
  299.  
  300. // 选择发布商品时机
  301. const radioElements = document.querySelectorAll(".el-radio");
  302. if (radioElements.length > 11) {
  303. radioElements[11].click();
  304. } else {
  305. console.error("未找到发布商品时机的单选框");
  306. showToast("未找到发布商品时机的单选框", "error");
  307. }
  308.  
  309. showToast("商品信息已填充");
  310. }, 500);
  311. }, 500);
  312. }
  313.  
  314. // 闲鱼详情页:提取并显示想要人数、浏览量和转化率
  315. if (window.location.href.includes("https://www.goofish.com/item")) {
  316. setTimeout(() => {
  317. const spanElement = document.querySelector(
  318. "#ice-container > div.content-container--gIWgkNkm > div.item-container--yLJD5VZj > div.item-main-container--jhpFKlaS > div.item-main-info--rA5Bmpa5 > div.tips--JYdXhSNh > div.want--mVAXJTGv"
  319. );
  320.  
  321. if (spanElement) {
  322. const textContent = spanElement.textContent.trim();
  323.  
  324. // 初始化变量
  325. let wantText = "0人想要";
  326. let viewText = "0浏览";
  327.  
  328. // 检查字符串内容并进行拆分和处理
  329. if (textContent.includes("人想要") && textContent.includes("浏览")) {
  330. // 如果同时包含 "人想要" 和 "浏览"
  331. [wantText, viewText] = textContent.split(" ");
  332. } else if (textContent.includes("浏览")) {
  333. // 只有 "浏览"
  334. viewText = textContent;
  335. }
  336.  
  337. // 提取数字部分并转换为整数
  338. const wantNumber =
  339. parseInt(wantText.replace("人想要", "").trim(), 10) || 0;
  340. const viewNumber =
  341. parseInt(viewText.replace("浏览", "").trim(), 10) || 0;
  342.  
  343. let rate = 0;
  344. if (wantNumber != 0 || viewNumber != 0) {
  345. rate = wantNumber / viewNumber;
  346. }
  347. const conversionRate = (rate * 100).toFixed(0);
  348. const conversionRateText = conversionRate + "%";
  349.  
  350. const statsDiv = document.createElement("div");
  351. statsDiv.style.position = "fixed";
  352. statsDiv.style.bottom = "63px";
  353. statsDiv.style.left = "20px";
  354. statsDiv.style.backgroundColor = "#93ab9b";
  355. statsDiv.style.borderRadius = "6px";
  356. statsDiv.style.color = "white";
  357. statsDiv.style.padding = "10px";
  358. statsDiv.style.zIndex = "1000";
  359. statsDiv.style.fontSize = "14px";
  360.  
  361. const conversionRateSpan = document.createElement("b");
  362. conversionRateSpan.textContent = conversionRateText;
  363. conversionRateSpan.style.backgroundColor =
  364. conversionRate > 7 ? "green" : "red";
  365. statsDiv.style.backgroundColor =
  366. conversionRate > 7 ? "#93ab9b" : "rgb(211 131 131)";
  367.  
  368. conversionRateSpan.style.padding = "2px 4px";
  369. conversionRateSpan.setAttribute("id", "conversion-rate");
  370.  
  371. statsDiv.innerHTML = `
  372. 想要数 : <b id="want-num">${wantNumber}</b><br>
  373. 浏览量 : <b id="view-num">${viewNumber}</b><br>
  374. 转化率 : `;
  375. statsDiv.appendChild(conversionRateSpan);
  376.  
  377. document.body.appendChild(statsDiv);
  378.  
  379. if (conversionRate < 7) {
  380. console.log(`转化率太低了 ${conversionRate}%`);
  381. }
  382. } else {
  383. console.error("无法找到目标 span 元素");
  384. }
  385. }, 1000);
  386. }
  387.  
  388. // 拦截并处理接口请求
  389. function interceptRequests() {
  390.  
  391.  
  392. // 覆盖原生的 XMLHttpRequest
  393. const originalXHR = unsafeWindow.XMLHttpRequest;
  394. unsafeWindow.XMLHttpRequest = function () {
  395. const xhr = new originalXHR();
  396.  
  397. // 保存原始的 open 方法
  398. const originalOpen = xhr.open;
  399. xhr.open = function (method, url, ...rest) {
  400. this._url = url; // 保存请求 URL
  401. return originalOpen.apply(this, [method, url, ...rest]);
  402. };
  403.  
  404. // 保存原始的 send 方法
  405. const originalSend = xhr.send;
  406. xhr.send = function (...args) {
  407. this.addEventListener("load", function () {
  408.  
  409. // 拦截商品详情接口,获取详情文本内容
  410. if (
  411. this._url.includes(
  412. "h5api.m.goofish.com/h5/mtop.taobao.idle.pc.detail"
  413. )
  414. ) {
  415. try {
  416. const data = JSON.parse(this.responseText);
  417. console.log("接收到的数据:", data);
  418. if (data?.data?.itemDO?.desc) {
  419. let productDescription = data.data.itemDO.desc;
  420. const goodsId = new URL(location.href).searchParams.get("id");
  421. productDescription += `\n \n[钉子]发的是百 接,永不失效,售出不退。
  422. [钉子]任何情况,不要申请退款,私信沟通给你处理,小店经营不易。
  423. [钉子]所有文件均获取自网络公开渠道,仅供学习和交流使用,所有版权归版权人所有,如版权方认为侵犯了您的版权,请及时联系小店删除。`;
  424. productDescription += `\n${goodsId}`;
  425. GM_setValue("productDescription", productDescription);
  426. console.log("商品详情:", productDescription);
  427. }
  428. } catch (error) {
  429. console.error("解析 XHR 响应时发生错误:", error);
  430. }
  431. }
  432.  
  433. // 拦截商品详情接口,获取详情文本内容
  434. if (
  435. this._url.includes(
  436. "h5api.m.goofish.com/h5/mtop.taobao.idle.item.web.recommend.list"
  437. )
  438. ) {
  439. try {
  440. const data = JSON.parse(this.responseText);
  441. console.log('接收到的数据:', data);
  442.  
  443. // 检查 data.data.cardList 是否为数组
  444. if (data && Array.isArray(data.data?.cardList)) {
  445. // 提取有效的数据
  446. const tempData = data.data.cardList.filter((item) => {
  447. if (item && item.cardData && item.cardData.itemId) {
  448. const price = parseInt(item.cardData.price);
  449. return price > 0;
  450. }
  451. return false;
  452. });
  453.  
  454. // 合并到全局数组 window.collectedData
  455. window.collectedData.push(...tempData);
  456. console.log('新数据已追加:', data.data.cardList);
  457.  
  458. // 去重:使用一个 Set 来追踪已经存在的 itemId
  459. const uniqueItems = [];
  460. const itemIdSet = new Set();
  461.  
  462. // 遍历 window.collectedData,添加未重复的 item
  463. for (const item of window.collectedData) {
  464. const itemId = item.cardData?.itemId;
  465. if (itemId && !itemIdSet.has(itemId)) {
  466. uniqueItems.push(item);
  467. itemIdSet.add(itemId);
  468. }
  469. }
  470.  
  471. // 更新 window.collectedData 为去重后的结果
  472. window.collectedData = uniqueItems;
  473.  
  474. console.log('去重后的数据:', window.collectedData);
  475.  
  476. // 更新数据计数
  477. updateDataCount();
  478. }
  479. } catch (error) {
  480. console.error("解析 XHR 响应时发生错误:", error);
  481. }
  482. }
  483. });
  484. return originalSend.apply(this, args);
  485. };
  486.  
  487. return xhr;
  488. };
  489. }
  490.  
  491. // 自动写入类目(暂定为电子资料)
  492. if (window.location.hostname.includes("goofish.pro")) {
  493. // 要写入的键
  494. const key = "goods_select";
  495.  
  496. // 要写入的值(注意是一个字符串)
  497. const value = JSON.stringify([
  498. {
  499. name: "电子资料",
  500. id: [
  501. 99,
  502. "eebfcb1cd9bfce8e212e21d79c0262e7",
  503. "eebfcb1cd9bfce8e212e21d79c0262e7",
  504. "3cdbae6d47df9251a7f7e02f36b0b49a",
  505. ],
  506. item_biz_type: 2,
  507. },
  508. ]);
  509.  
  510. // 检查localStorage中是否已经存在该键
  511. if (!localStorage.getItem(key)) {
  512. // 将键值对写入localStorage
  513. localStorage.setItem(key, value);
  514. console.log(`已写入localStorage: ${key} = ${value}`);
  515. } else {
  516. console.log(
  517. `localStorage中已存在: ${key} = ${localStorage.getItem(key)}`
  518. );
  519. }
  520. }
  521.  
  522. repleaceUrl();
  523. // 避免闲管家的域名混用,带www和不带www的,因为两者的cookie不同,导致登录(不可用)状态是不共享的
  524. function repleaceUrl() {
  525. // 获取当前页面的 URL
  526. const currentUrl = window.location.href;
  527.  
  528. // 判断是否是以 'https://www.goofish.pro/' 开头
  529. if (currentUrl.startsWith("https://www.goofish.pro/")) {
  530. // 使用正则表达式替换 'www.' 为 ''
  531. const newUrl = currentUrl.replace("https://www.", "https://");
  532.  
  533. // 跳转到新的 URL
  534. window.location.replace(newUrl);
  535. }
  536. }
  537.  
  538. // 闲鱼商详页导出猜你喜欢的数据到Excel,支持动态数据
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545. if (window.location.href.includes("https://www.goofish.com/item?")) {
  546. exportGoodsList()
  547. }
  548.  
  549. // 更新商品数量显示
  550. function updateDataCount() {
  551. const countElement = document.getElementById('data-count');
  552. if (countElement) {
  553. countElement.innerText = window.collectedData.length;
  554. }
  555. }
  556.  
  557. function exportGoodsList () {
  558.  
  559. setTimeout(() => {
  560. insertDownloadButton();
  561. }, 0);
  562.  
  563. // 全局数组,用于存储商品数据,确保全局数据存储在 window 对象上
  564. if (!window.collectedData) {
  565. window.collectedData = [];
  566. }
  567.  
  568. interceptRequests();
  569.  
  570. // 插入下载按钮到页面
  571. function insertDownloadButton() {
  572. const button = document.createElement('button');
  573. button.innerHTML = `导出 [猜你喜欢] 商品 (<b id="data-count">0</b>)`;
  574. button.style.position = 'fixed';
  575. button.style.width = '240px';
  576. button.style.left = '50%';
  577. button.style.marginLeft = '-120px';
  578. button.style.bottom = '20px';
  579. button.style.zIndex = 9999;
  580. button.style.padding = '10px 20px';
  581. button.style.backgroundColor = 'rgb(40, 167, 69)';
  582. button.style.color = '#FFFFFF';
  583. button.style.border = 'none';
  584. button.style.borderRadius = '5px';
  585. button.style.cursor = 'pointer';
  586. button.addEventListener('click', downloadExcel);
  587. document.body.appendChild(button);
  588. }
  589.  
  590. // 时间戳转换成日期格式
  591. function timestampToFormattedDate(timestamp) {
  592. if (!timestamp) return "";
  593. var date = new Date(parseInt(timestamp));
  594. var year = date.getFullYear(); // 获取年份
  595. var month = date.getMonth() + 1; // 获取月份,月份是从0开始的,所以需要加1
  596. var day = date.getDate(); // 获取日期
  597.  
  598. // 月份和日期如果是单数,需要在前面补0
  599. month = month < 10 ? '0' + month : month;
  600. day = day < 10 ? '0' + day : day;
  601.  
  602. return `${year}-${month}-${day}`;
  603. }
  604.  
  605. // 下载Excel文件
  606. function downloadExcel() {
  607. if (window.collectedData.length === 0) {
  608. alert('没有数据可导出');
  609. return;
  610. }
  611.  
  612. // 创建Excel工作簿
  613. const workbook = XLSX.utils.book_new();
  614. const worksheetData = window.collectedData.map((item) => {
  615. console.log(111, item.cardData?.trackEventParamInfo?.args?.publishTime)
  616. return {
  617. //商品ID: item.cardData.itemId || '',
  618. //链接: `https://www.goofish.com/item?id=` + item.cardData.itemId,
  619. 链接: {
  620. f: `HYPERLINK("https://www.goofish.com/item?id=${item.cardData.itemId}", "https://www.goofish.com/item?id=${item.cardData.itemId}")`
  621. },
  622. 标题: {
  623. f: `HYPERLINK("https://www.goofish.com/item?id=${item.cardData.itemId}", "${item.cardData.title}")`
  624. },
  625. 想要数: parseInt(item.cardData.clickParam.args.wantNum, 10) || '',
  626. 价格: parseInt(item.cardData.price) - 0.1 || '',
  627. 城市: item.cardData.area || '',
  628. 发布日期: timestampToFormattedDate(item.cardData?.clickParam?.args?.publishTime)
  629.  
  630. }
  631. })
  632. .sort((a, b) => b.想要数 - a.想要数);;
  633.  
  634. // 将数据转化为工作表
  635. const worksheet = XLSX.utils.json_to_sheet(worksheetData);
  636. XLSX.utils.book_append_sheet(workbook, worksheet, '猜你喜欢');
  637.  
  638. // 生成Excel并触发下载
  639. const workbookOut = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
  640. const blob = new Blob([workbookOut], { type: 'application/octet-stream' });
  641. const url = URL.createObjectURL(blob);
  642. const a = document.createElement('a');
  643. a.href = url;
  644. a.download = '猜你喜欢商品.xlsx';
  645. document.body.appendChild(a);
  646. a.click();
  647. document.body.removeChild(a);
  648. URL.revokeObjectURL(url);
  649. }
  650. }
  651. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址