// ==UserScript== // @name 浩毅工具箱(组合+绑定SKU)左侧固定版 // @namespace http://tampermonkey.net/ // @version 3.2 // @description 左侧垂直排列:双合成编号组合 + 批量绑定SKU | 全局统一样式 | 默认隐藏 // @author helper // @match https://www2.haoyipod.com/workbenchcustommade // @match https://www2.haoyipod.com/workbenchgroupcustommade // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; // ====================== 全局统一配置 ====================== const TOKEN = '6eba73fc-77da-4d26-8887-a791acc3b2b4'; const WIDTH = '280px'; const PADDING = '16px'; const RADIUS = '12px'; const SHADOW = '0 6px 20px rgba(0, 0, 0, 0.08)'; const BORDER = '1px solid #e8e8e8'; const BTN_BG = '#3b82f6'; const BTN_SUCCESS = '#10b981'; let checkInterval = null; let isVisible = false; // 默认隐藏 // ====================== 主容器(统一包裹两个功能) ====================== function createToolPanel() { const root = document.createElement('div'); root.style.cssText = ` position: fixed; left: 20px; top: 50%; transform: translateY(-50%); z-index: 99999; width: ${WIDTH}; display: flex; flex-direction: column; gap: 12px; `; // 功能1:双合成编号组合 const panel1 = createCombinePanel(); // 功能2:批量绑定SKU const panel2 = createBindSkuPanel(); // 开关按钮 const toggleBtn = createToggleBtn(); root.append(panel1, panel2, toggleBtn); document.body.appendChild(root); return root; } // ====================== 开关按钮:显示/隐藏全部 ====================== function createToggleBtn() { const btn = document.createElement('button'); btn.innerText = '浩毅工具'; btn.style.cssText = ` padding: 10px; background: ${BTN_BG}; color: #fff; border: none; border-radius: ${RADIUS}; font-size: 14px; cursor: pointer; box-shadow: ${SHADOW}; `; btn.onclick = () => { isVisible = !isVisible; const panels = document.querySelectorAll('.tool-panel'); panels.forEach(p => p.style.display = isVisible ? 'block' : 'none'); }; return btn; } // ====================== 功能1:双合成编号组合 ====================== function createCombinePanel() { const box = document.createElement('div'); box.className = 'tool-panel'; box.style.cssText = ` background: #fff; border: ${BORDER}; border-radius: ${RADIUS}; padding: ${PADDING}; box-shadow: ${SHADOW}; display: none; `; box.innerHTML = `

双合成编号组合

`; // 注入通用样式 addGlobalStyle(); setTimeout(() => { const startBtn = document.getElementById('startCombine'); const taskId1 = document.getElementById('taskId1'); const taskId2 = document.getElementById('taskId2'); const logBox = document.getElementById('combineLog'); const headers = { token: TOKEN, 'Content-Type': 'application/json' }; async function getSizeMap(taskId) { const listUrl = `https://crossdiy2.haoyipod.com/api/finished/getlist?task_id=${taskId}&pageNumber=1&pageSize=10&is_online=0`; const res = await fetch(listUrl, { headers }); const data = await res.json(); const fid = data.data?.list?.[0]?.id; if (!fid) throw new Error('未获取到成品ID'); const sizeRes = await fetch(`https://crossdiy2.haoyipod.com/api/finished/addToCartsPage?id=${fid}`, { headers }); const sizeData = await sizeRes.json(); const map = {}; sizeData.data?.forEach(i => map[i.size] = i.id); return map; } async function createCombine(f1, f2, size) { return fetch('https://crossdiy2.haoyipod.com/api/finished_combination/add', { method: 'POST', headers, body: JSON.stringify({ finished_ids: [f1, f2], finished_nums: [1,1], combine_name: size }) }); } startBtn.onclick = async () => { const t1 = taskId1.value.trim(); const t2 = taskId2.value.trim(); if (!t1 || !t2) return alert('请输入两个编号'); startBtn.disabled = true; startBtn.innerText = '处理中...'; logBox.style.display = 'none'; let log = ''; try { const map1 = await getSizeMap(t1); const map2 = await getSizeMap(t2); const sizes = Object.keys(map1).filter(s => map2[s]); if (!sizes.length) throw new Error('无共同尺码'); log += `找到 ${sizes.length} 个共同尺码\n`; let ok = 0; for (let s of sizes) { log += `[${s}] `; await createCombine(map1[s], map2[s], s); ok++; log += '✅ 成功\n'; await new Promise(r => setTimeout(r, 300)); } log += `\n完成:${ok}/${sizes.length}`; } catch (e) { log += '❌ 错误:' + e.message; alert(e.message); } logBox.innerText = log; logBox.style.display = 'block'; startBtn.disabled = false; startBtn.innerText = '开始组合生成'; }; }, 100); return box; } // ====================== 功能2:批量绑定SKU(新版:先获取→预览→反向→统一提交) ====================== function createBindSkuPanel() { const box = document.createElement('div'); box.className = 'tool-panel'; box.style.cssText = ` background: #fff; border: ${BORDER}; border-radius: ${RADIUS}; padding: ${PADDING}; box-shadow: ${SHADOW}; display: none; `; box.innerHTML = `

批量绑定第三方SKU

`; setTimeout(() => { const skuInput = document.getElementById('skuList'); const loadMatchBtn = document.getElementById('loadMatch'); const reverseMatchBtn = document.getElementById('reverseMatch'); const startBindBtn = document.getElementById('startBind'); const previewBox = document.getElementById('matchPreview'); // 全局存储:尺码列表 + SKU列表 let sizeList = []; // [{ id, name }] let skuList = []; let isReversed = false; // 自动加复选框 function addCheckboxes() { const wrapper = document.querySelector(".el-table__body-wrapper"); if (!wrapper) return; const tbody = wrapper.querySelector("tbody"); if (!tbody) return; tbody.querySelectorAll("tr").forEach(tr => { if (tr.querySelector('input[type="checkbox"]')) return; const td = tr.querySelector(".el-table_1_column_6 .cell"); if (!td) return; const btn = td.querySelector("button"); if (!btn) return; const ck = document.createElement("input"); ck.type = "checkbox"; ck.style.marginRight = "8px"; ck.style.verticalAlign = "middle"; td.insertBefore(ck, btn); }); } checkInterval = setInterval(addCheckboxes, 1000); // 1)加载:先获取所有勾选的尺码ID+名称 loadMatchBtn.onclick = async () => { skuList = skuInput.value.trim().split(/\s+/).filter(Boolean); if (skuList.length === 0) return alert('请输入SKU'); // 获取勾选行 const tbody = document.querySelector(".el-table__body-wrapper tbody"); const rows = Array.from(tbody.querySelectorAll("input[type='checkbox']:checked")).map(c => c.closest("tr")); if (rows.length === 0) return alert('请勾选要绑定的尺码'); sizeList = []; for (const tr of rows) { const no = tr.querySelector("td:first-child")?.textContent?.trim(); if (!no) continue; try { const res = await fetch(`https://crossdiy2.haoyipod.com/api/finished_combination/index?combine_no=${no}`, { headers: { token: TOKEN } }); const data = await res.json(); const item = data.data?.list?.[0]; if (item) sizeList.push({ id: item.id, name: item.combine_name }); } catch (e) {} } if (sizeList.length !== skuList.length) { return alert(`勾选尺码数(${sizeList.length}) ≠ SKU数(${skuList.length})`); } isReversed = false; renderPreview(); reverseMatchBtn.style.display = 'inline-block'; startBindBtn.style.display = 'block'; }; // 2)渲染预览 function renderPreview() { const sList = isReversed ? [...sizeList].reverse() : sizeList; let html = '📋 配对预览(尺码 ↔ SKU)\n'; html += '-----------------------------------\n'; sList.forEach((s, i) => { html += `${s.name} ↔ ${skuList[i]}\n`; }); previewBox.innerText = html; previewBox.style.display = 'block'; } // 3)反向 reverseMatchBtn.onclick = () => { isReversed = !isReversed; renderPreview(); }; // 4)统一提交绑定 startBindBtn.onclick = async () => { if (!sizeList.length || !skuList.length) return; startBindBtn.disabled = true; startBindBtn.innerText = '绑定中...'; const sList = isReversed ? [...sizeList].reverse() : sizeList; const headers = { token: TOKEN, 'Content-Type': 'application/json' }; for (let i = 0; i < sList.length; i++) { try { await fetch("https://crossdiy2.haoyipod.com/api/finished_combination/addBindThirdSku", { method: "POST", headers, body: JSON.stringify({ combine_id: sList[i].id, params: [{ id: 0, import_sku: skuList[i] }] }) }); } catch (e) {} } alert('✅ 全部绑定完成!'); startBindBtn.disabled = false; startBindBtn.innerText = '🚀 确认绑定'; }; }, 100); return box; } // ====================== 全局统一样式 ====================== function addGlobalStyle() { if (document.querySelector('#tool-global-style')) return; const style = document.createElement('style'); style.id = 'tool-global-style'; style.textContent = ` .tool-input { width: 100%; box-sizing: border-box; padding: 10px 12px; margin-bottom: 10px; border: 1px solid #dcdfe6; border-radius: 8px; font-size: 14px; outline: none; transition: border-color 0.2s; } .tool-input:focus { border-color: ${BTN_BG}; } .tool-textarea { width: 100%; box-sizing: border-box; height: 90px; padding: 10px 12px; border: 1px solid #dcdfe6; border-radius: 8px; font-size: 14px; resize: none; outline: none; margin-bottom: 12px; } .tool-btn { width: 100%; padding: 10px; border: none; border-radius: 8px; color: #fff; font-size: 14px; cursor: pointer; transition: opacity 0.2s; } .tool-btn.primary { background: ${BTN_BG}; } .tool-btn.success { background: ${BTN_SUCCESS}; } .tool-btn:hover { opacity: 0.9; } .tool-log { margin-top: 12px; padding: 10px; background: #f8f9fa; border-radius: 8px; font-size: 12px; max-height: 260px; overflow-y: auto; white-space: pre-wrap; display: none; } `; document.head.appendChild(style); } // 启动 window.addEventListener('load', createToolPanel); })();