// ==UserScript== // @name 抖店达人助手 // @namespace https://github.com/yourusername // @version 2.3.5 // @author WechatID:fmtprint // @description 抖店达人拓展好帮手 // @license MIT // @match https://buyin.jinritemai.com/dashboard/servicehall/business-homepage?sec_shop_id* // @connect shop_api.uinstall.eu.org // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== (function () { 'use strict'; const e = { templates: [], productSettings: {}, productIds: [], contactInfo: { phone: "", wechat: "" }, activeTemplateId: "" }, t = "INVITE_CARD_CONFIG"; function getConfig() { const n = GM_getValue(t, e); return { templates: n.templates || e.templates, productSettings: n.productSettings || {}, productIds: n.productIds || [], contactInfo: { phone: n.contactInfo?.phone || "", wechat: n.contactInfo?.wechat || "" }, activeTemplateId: n.activeTemplateId || e.activeTemplateId }; } function saveConfig(e) { GM_setValue(t, e); } function debounce(e, t) { let n; return (...o) => { clearTimeout(n), n = window.setTimeout((() => e(...o)), t); }; } function createConfigPanel() { const e = document.createElement("div"); e.className = "shop-config-overlay", e.style.cssText = "position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:1000;display:none;"; const t = document.createElement("div"); t.className = "shop-config-panel", t.style.cssText = "position:fixed;top:0;right:0;width:960px;height:100vh;background:white;box-shadow:-2px 0 8px rgba(0,0,0,0.15);z-index:1001;display:flex;flex-direction:column;font-size:14px;"; const n = document.createElement("style"); n.textContent = "\n .shop-config-panel .header { padding:16px 24px; border-bottom:1px solid #f0f0f0; display:flex; justify-content:space-between; align-items:center; background:white; }\n .shop-config-panel .content { flex:1; overflow-y:auto; padding:16px; background-color:#fafbfc; display:flex; gap:16px; }\n .shop-config-panel .footer { padding:16px 24px; border-top:1px solid #f0f0f0; text-align:right; background:white; }\n .shop-config-panel h3 { margin:0; color:#000000d9; font-weight:500; font-size:16px; }\n .shop-config-panel .form-block { background:white; border-radius:2px; padding:16px; margin-bottom:16px; }\n .shop-config-panel .highlight-text { font-size:14px; font-weight:500; color:#000000d9; margin-bottom:16px; display:flex; align-items:center; }\n .shop-config-panel .form-row { display:flex; margin-bottom:16px; }\n .shop-config-panel .form-label { width:120px; text-align:right; padding-right:16px; color:#898b8f; line-height:32px; }\n .shop-config-panel .form-content { flex:1; }\n .shop-config-panel input[type=\"text\"], .shop-config-panel textarea { width:288px; padding:4px 11px; border:1px solid #d9d9d9; border-radius:2px; font-size:14px; }\n .shop-config-panel textarea.large { width:100%; height:160px; resize:none; }\n .shop-config-panel .checkbox-group { display:flex; flex-wrap:wrap; gap:16px; }\n .shop-config-panel .checkbox-wrapper { display:inline-flex; align-items:center; cursor:pointer; user-select:none; }\n .shop-config-panel .checkbox-inner { position:relative; width:16px; height:16px; border:1px solid #d9d9d9; border-radius:2px; margin-right:8px; }\n .shop-config-panel .checkbox-wrapper.checked .checkbox-inner { background:#1966ff; border-color:#1966ff; }\n .shop-config-panel .checkbox-wrapper.checked .checkbox-inner:after { content:''; position:absolute; left:4px; top:1px; width:6px; height:9px; border:2px solid #fff; border-top:0; border-left:0; transform:rotate(45deg); }\n .shop-config-panel .table { width:100%; border-collapse:collapse; }\n .shop-config-panel .table th, .shop-config-panel .table td { padding:12px 16px; border-bottom:1px solid #f0f0f0; text-align:left; vertical-align:middle; }\n .shop-config-panel .table th { background:#fafafa; font-weight:500; color:#000000d9; }\n .shop-config-panel .product-card { display:flex; align-items:center; gap:12px; }\n .shop-config-panel .product-image { width:32px; height:32px; border-radius:2px; object-fit:cover; }\n .shop-config-panel .product-info { flex:1; min-width:0; }\n .shop-config-panel .product-title { font-size:13px; margin-bottom:4px; color:#252931; }\n .shop-config-panel .product-meta { color:#898b8f; font-size:12px; }\n .shop-config-panel .switch { position:relative; display:inline-block; width:28px; height:16px; background:#ccc; border-radius:100px; cursor:pointer; vertical-align:middle; }\n .shop-config-panel .switch.checked { background:#1966ff; }\n .shop-config-panel .switch-handle { position:absolute; top:2px; left:2px; width:12px; height:12px; background:white; border-radius:50%; transition:left 0.2s; }\n .shop-config-panel .switch.checked .switch-handle { left:14px; }\n .shop-config-panel .btn { padding:4px 15px; border-radius:2px; border:1px solid #d9d9d9; background:white; cursor:pointer; font-size:14px; }\n .shop-config-panel .btn-primary { background:#1966ff; border-color:#1966ff; color:white; }\n .shop-config-panel .btn-link { border:none; padding:0; color:#1966ff; }\n .shop-config-panel .set-end-time { min-width:80px; text-align:left; }\n ", document.head.appendChild(n); const o = document.createElement("div"); o.className = "header", o.innerHTML = '\n

\u9080\u8bf7\u914d\u7f6e

\n \n '; const i = document.createElement("div"); i.className = "content"; const a = document.createElement("div"); a.style.flex = "1"; const r = document.createElement("div"); r.className = "form-block", r.innerHTML = '\n
\u9080\u7ea6\u4fe1\u606f
\n
\n
\u9080\u7ea6\u5185\u5bb9
\n
\n \n
\n
\n
\n
\u4e13\u5c5e\u6743\u76ca
\n
\n
\n \n \n \n \n
\n
\n
\n '; const c = document.createElement("div"); c.className = "form-block", c.innerHTML = '\n
\u8054\u7cfb\u65b9\u5f0f
\n
\n
\u624b\u673a\u53f7
\n
\n \n
\n
\n
\n
\u5fae\u4fe1\u53f7
\n
\n \n
\n
\n '; const s = document.createElement("div"); s.className = "form-block", s.innerHTML = '\n
\u5546\u54c1\u914d\u7f6e
\n
\n \n
\n \n \n \n \n \n \n \n \n \n \n \n
\u5546\u54c1\u4fe1\u606f\u4e13\u5c5e\u4f63\u91d1\u514d\u5ba1\u7533\u6837\u7b56\u7565\u7ed3\u675f\u65f6\u95f4\u64cd\u4f5c
\n ', a.appendChild(r), a.appendChild(c), a.appendChild(s), i.appendChild(a); const l = document.createElement("div"); l.style.cssText = "width:286px;flex-shrink:0;", l.innerHTML = '\n
\u6548\u679c\u9884\u89c8
\n \n ', i.appendChild(l); const d = document.createElement("div"); d.className = "footer", d.innerHTML = ''; const p = document.createElement("button"); p.textContent = "\u9884\u89c8\u914d\u7f6e", p.className = "btn", p.style.marginRight = "8px", p.onclick = () => (function showPreviewDialog() { const e = convertConfigToRequestBody("preview_account_id"), t = JSON.stringify(e, null, 2), n = document.createElement("div"); n.style.cssText = "position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:white;padding:24px;border-radius:2px;box-shadow:0 3px 6px -4px rgba(0,0,0,.12),0 6px 16px 0 rgba(0,0,0,.08);z-index:1002;width:800px;max-height:90vh;display:flex;flex-direction:column;", n.innerHTML = `\n
\n

\u914d\u7f6e\u9884\u89c8

\n \n
\n
${t}
\n `, n.querySelector("button").onclick = () => document.body.removeChild(n), document.body.appendChild(n); })(), d.insertBefore(p, d.firstChild), t.appendChild(o), t.appendChild(i), t.appendChild(d), e.appendChild(t); [ o.querySelector("button"), d.querySelector(".btn:last-child") ].forEach((n => { n.onclick = () => { e.style.display = "none", t.style.display = "none"; }; })), e.onclick = n => { n.target === e && (e.style.display = "none", t.style.display = "none"); }; const h = getConfig(), f = r.querySelector("textarea"); f.value = h.templates[0]?.content || "", f.onchange = debounce((e => { const t = getConfig(), n = e.target.value, o = "template_" + Date.now(); 0 === t.templates.length ? (t.templates.push({ id: o, name: "\u9080\u7ea6\u6a21\u677f", content: n, rights: [ { right: 1 }, { right: 2 } ] }), t.activeTemplateId = o) : t.templates[0].content = n, saveConfig(t); }), 300); r.querySelectorAll(".checkbox-wrapper").forEach(((e, t) => { const n = h.templates[0]?.rights || [ { right: 1 }, { right: 2 } ], o = [ 1, 2, 4, 3 ][t]; n.some((e => e.right === o)) && e.classList.add("checked"), e.onclick = () => { const t = getConfig(); e.classList.contains("checked") ? (e.classList.remove("checked"), t.templates[0].rights = t.templates[0].rights.filter((e => e.right !== o))) : (e.classList.add("checked"), t.templates[0].rights.push({ right: o })), saveConfig(t); }; })); const [u, g] = c.querySelectorAll("input"); u.value = h.contactInfo.phone, g.value = h.contactInfo.wechat, u.onchange = debounce((e => { const t = e.target.value; if (!(function validatePhoneNumber(e) { return /^1[3-9]\d{9}$/.test(e); })(t)) return void window.alert("\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u624b\u673a\u53f7\u7801"); const n = getConfig(); n.contactInfo.phone = t, saveConfig(n); }), 300), g.onchange = debounce((e => { const t = e.target.value; if (!(function validateWechat(e) { return /^[a-zA-Z0-9_-]{6,20}$/.test(e); })(t)) return void window.alert("\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u5fae\u4fe1\u53f7\uff086-20\u4f4d\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u4e0b\u5212\u7ebf\uff09"); const n = getConfig(); n.contactInfo.wechat = t, saveConfig(n); }), 300); const m = s.querySelector("tbody"); function renderProductList() { const e = getConfig(); m.innerHTML = e.productIds.map((t => { const n = e.productSettings[t], o = n?.validTime && "end" === n.timeRadio ? n.validTime.split(" ")[0] : "\u957f\u671f"; return `\n \n \n
\n \n
\n
\u5546\u54c1ID: ${t}
\n
\n \u4f63\u91d1\uff1a${n?.cosRatio || 0}%\n
\n
\n
\n \n \n \n \n \n
\n
\n
\n \n \n \n \n \n \n \n \n `; })).join(""), m.querySelectorAll("[data-id]").forEach((e => { const t = e.getAttribute("data-id"); e.classList.contains("set-ratio") ? e.onclick = () => { const e = getConfig(), n = e.productSettings[t]?.cosRatio || 40, o = prompt("\u8bf7\u8f93\u5165\u4e13\u5c5e\u4f63\u91d1\u6bd4\u4f8b\uff08%\uff09", n.toString()); if (null !== o) { const n = parseInt(o); !isNaN(n) && n >= 0 && n <= 100 ? (e.productSettings[t].cosRatio = n, saveConfig(e), renderProductList()) : window.alert("\u8bf7\u8f93\u51650-100\u4e4b\u95f4\u7684\u6709\u6548\u6570\u5b57"); } } : e.classList.contains("switch") ? e.onclick = () => { const e = getConfig(), n = e.productSettings[t].sampleStatus; e.productSettings[t].sampleStatus = 3 === n ? 1 : 3, saveConfig(e), renderProductList(); } : e.classList.contains("set-end-time") ? e.onclick = () => { const e = getConfig(), n = e.productSettings[t]; if ("long" === n.timeRadio) { if (confirm("\u662f\u5426\u8bbe\u7f6e\u7b56\u7565\u675f\u65f6\u95f4\uff1f")) { const t = new Date, o = new Date(t.getTime() + 6048e5), i = document.createElement("input"); i.type = "date", i.value = o.toISOString().split("T")[0], i.min = t.toISOString().split("T")[0], i.style.cssText = "\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n padding: 8px;\n border: 1px solid #d9d9d9;\n border-radius: 2px;\n font-size: 14px;\n z-index: 1003;\n ", document.body.appendChild(i); const a = document.createElement("div"); a.style.cssText = "\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0,0,0,0.5);\n z-index: 1002;\n ", document.body.appendChild(a), a.onclick = () => { document.body.removeChild(i), document.body.removeChild(a); }, i.onchange = t => { const o = t.target.value; n.timeRadio = "end", n.validTime = `${o} 23:59:59`, saveConfig(e), renderProductList(), document.body.removeChild(i), document.body.removeChild(a); }, setTimeout((() => { i.focus(); }), 100); } } else confirm("\u662f\u5426\u6539\u4e3a\u957f\u671f\uff1f") && (n.timeRadio = "long", n.validTime = "3000-01-01 00:00:00", saveConfig(e), renderProductList()); } : e.classList.contains("delete-product") && (e.onclick = () => { if (confirm("\u786e\u5b9a\u5220\u9664\u8be5\u5546\u54c1\u5417\uff1f")) { const e = getConfig(); e.productIds = e.productIds.filter((e => e !== t)), delete e.productSettings[t], saveConfig(e), renderProductList(); } }); })); } return s.querySelector(".btn-primary").onclick = () => { const e = prompt("\u8bf7\u8f93\u5165\u5546\u54c1ID"); if (!e) return; if (!(function validateProductId(e) { return /^\d{6,20}$/.test(e); })(e)) return void window.alert("\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u5546\u54c1ID\uff086-20\u4f4d\u6570\u5b57\uff09"); const t = getConfig(); t.productIds.includes(e) ? window.alert("\u8be5\u5546\u54c1\u5df2\u6dfb\u52a0") : (t.productIds.push(e), t.productSettings[e] = { sampleStatus: 1, cosRatio: 40, timeRadio: "long", validTime: "3000-01-01 00:00:00" }, saveConfig(t), renderProductList()); }, renderProductList(), e; } function showConfigPanel() { const e = document.querySelector(".shop-config-overlay"); if (e) e.style.display = "block", e.querySelector(".shop-config-panel").style.display = "flex"; else { const e = createConfigPanel(); document.body.appendChild(e), e.style.display = "block", e.querySelector(".shop-config-panel").style.display = "flex"; } } const n = {}, o = {}, i = { name: "", avatar: "", shopId: "" }; function convertConfigToRequestBody(e) { const t = getConfig(), n = t.templates.find((e => e.id === t.activeTemplateId)); if (!n) throw new Error("Template not found"); return { account_id: e, account_type: 1, invite_card: { content: n.content, rights: n.rights, product_ids: t.productIds, product_setting: t.productIds.filter((e => t.productSettings[e])).map((e => { const n = t.productSettings[e]; return { product_id: e, author_sample_status: n.sampleStatus, orient_cos_ratio_detail: { orient_kol_cos_ratio: n.cosRatio, time_radio: n.timeRadio, valid_time: n.validTime || "3000-01-01 00:00:00", suggest_orient_kol_cos_ratio: 53, ...n.cosRatio ? {} : { cos_ratio_range: { low: 0, high: 80 } } } }; })) }, contact_info: t.contactInfo }; } function getShopProfile(e) { const t = (function findAuthorByAvatar(e) { const t = o[e]; if (!t) return null; const i = n[t]; return i?.data?.author_list ? i.data.author_list.find((t => t.avatar === e)) : null; })(e); return t || null; } function extractAvatarUrl(e) { const t = e.querySelector(".card-info__avatar img"), n = t?.getAttribute("src") || null; return n || null; } function getShopProfileFromElement(e) { const t = extractAvatarUrl(e); return t ? getShopProfile(t) : null; } function getShopProfilesFromElements(e) { return (function getShopProfiles(e) { return e.map((e => getShopProfile(e))).filter((e => null !== e)); })(e.map(extractAvatarUrl).filter((e => null !== e))); } async function queryContact(e) { return new Promise(((t, n) => { "undefined" != typeof GM_xmlhttpRequest ? GM_xmlhttpRequest({ method: "POST", url: "https://shop_api.uinstall.eu.org:888/shop/api/v1/douyin/contact", headers: { "Content-Type": "application/json", "User-Agent": window.navigator.userAgent, Accept: "application/json", Origin: "https://buyin.jinritemai.com", Referer: "https://buyin.jinritemai.com/", Cookie: document.cookie }, data: JSON.stringify(e), onload: function(e) { try { const o = JSON.parse(e.responseText); 200 === e.status && 200 === o.code ? t(o) : n(new Error(o.message || "\u8bf7\u6c42\u5931\u8d25")); } catch (o) { n(o); } }, onerror: function(e) { n(new Error("\u7f51\u7edc\u8bf7\u6c42\u5931\u8d25")); } }) : n(new Error("GM_xmlhttpRequest \u4e0d\u53ef\u7528")); })); } async function sendInvite(e) { try { const t = await fetch("https://buyin.jinritemai.com/connection/pc/im/invite/card/send", { method: "POST", headers: { "Content-Type": "application/json", "User-Agent": window.navigator.userAgent, Accept: "application/json", Origin: "https://buyin.jinritemai.com", Referer: "https://buyin.jinritemai.com/" }, body: JSON.stringify(e), credentials: "include" }); if (!t.ok) throw new Error(`HTTP error! status: ${t.status}`); const n = await t.json(); if (0 === n.code) return n; throw new Error(n.msg || "\u8bf7\u6c42\u5931\u8d25"); } catch (t) { throw t; } } function formatDateTime(e) { try { return new Date(e).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: !1 }); } catch (t) { return e; } } const a = { info: '', success: '', error: '', clear: '', minimize: '' }; let r = null, c = null; const s = new Map; function createLogPanel() { const e = document.createElement("div"); e.className = "shop-log-panel", e.style.cssText = "\n position: fixed;\n left: 0;\n bottom: 0;\n width: 360px;\n background: white;\n border-radius: 8px 8px 0 0;\n box-shadow: 0 2px 8px rgba(0,0,0,0.15);\n z-index: 1000;\n font-size: 12px;\n display: flex;\n flex-direction: column;\n max-height: 400px;\n transition: transform 0.3s ease;\n "; const t = document.createElement("div"); t.style.cssText = "\n padding: 12px 16px;\n border-bottom: 1px solid #f0f0f0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-radius: 8px 8px 0 0;\n background: #fafafa;\n cursor: move;\n "; const n = document.createElement("div"); n.style.cssText = "\n display: flex;\n align-items: center;\n gap: 8px;\n "; const o = document.createElement("span"); o.textContent = "\u64cd\u4f5c\u65e5\u5fd7", o.style.cssText = "\n font-weight: 500;\n color: #333;\n font-size: 13px;\n "; const i = document.createElement("div"); i.style.cssText = "\n display: flex;\n gap: 8px;\n "; const s = document.createElement("button"); s.innerHTML = `${a.minimize}`, s.style.cssText = "\n padding: 0 8px;\n height: 24px;\n background: none;\n border: 1px solid #d9d9d9;\n border-radius: 4px;\n cursor: pointer;\n color: #666;\n display: inline-flex;\n align-items: center;\n transition: all 0.3s;\n &:hover {\n color: #40a9ff;\n border-color: #40a9ff;\n }\n "; const l = document.createElement("button"); l.innerHTML = `${a.clear}\u6e05\u7a7a`, l.style.cssText = "\n padding: 0 8px;\n height: 24px;\n background: none;\n border: 1px solid #d9d9d9;\n border-radius: 4px;\n cursor: pointer;\n color: #666;\n display: inline-flex;\n align-items: center;\n transition: all 0.3s;\n &:hover {\n color: #40a9ff;\n border-color: #40a9ff;\n }\n "; let d = !1; s.onclick = () => { d = !d, e.style.transform = d ? `translateY(${e.offsetHeight - t.offsetHeight}px)` : "translateY(0)"; }, l.onclick = clearLog, n.appendChild(o), i.appendChild(s), i.appendChild(l), t.appendChild(n), t.appendChild(i); const p = document.createElement("div"); p.style.cssText = "\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n max-height: 320px;\n ", e.appendChild(t), e.appendChild(p), r = e, c = p; let h, f, u, g, m = !1; return t.addEventListener("mousedown", (t => { m = !0, u = t.clientX - e.offsetLeft, g = t.clientY - e.offsetTop; })), document.addEventListener("mousemove", (t => { if (m) { t.preventDefault(), h = t.clientX - u, f = t.clientY - g; const n = window.innerWidth - e.offsetWidth, o = window.innerHeight - e.offsetHeight; h = Math.max(0, Math.min(h, n)), f = Math.max(0, Math.min(f, o)), e.style.left = `${h}px`, e.style.bottom = window.innerHeight - f - e.offsetHeight + "px"; } })), document.addEventListener("mouseup", (() => { m = !1; })), e; } function addLogEntry(e, t, n) { if (!c) return; if (n && s.has(n)) { return void (s.get(n).querySelector(".log-message").textContent = e); } const o = document.createElement("div"); o.style.cssText = "\n padding: 4px 16px;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n line-height: 1.6;\n &:hover {\n background: #f5f5f5;\n }\n "; const i = document.createElement("span"); i.style.cssText = `\n margin-top: 2px;\n flex-shrink: 0;\n color: ${"info" === t.type ? "#1890ff" : "success" === t.type ? "#52c41a" : "#ff4d4f"};\n `, i.innerHTML = "info" === t.type ? a.info : "success" === t.type ? a.success : a.error; const r = document.createElement("span"); r.style.cssText = "\n color: #999;\n font-size: 11px;\n flex-shrink: 0;\n min-width: 50px;\n ", r.textContent = (new Date).toLocaleTimeString("zh-CN", { hour12: !1 }); const l = document.createElement("span"); if (l.className = "log-message", l.style.cssText = "\n flex: 1;\n word-break: break-all;\n white-space: pre-wrap;\n ", l.textContent = e, t.details) { const e = document.createElement("span"); e.style.cssText = "\n color: #999;\n font-size: 11px;\n flex-shrink: 0;\n margin-left: 8px;\n "; const n = []; "db" === t.details.source && t.details.savedAt && n.push(`DB:${formatDateTime(t.details.savedAt)}`), "api" === t.details.source && void 0 !== t.details.remaining && n.push(`API:${t.details.remaining}`), t.details.errorMessage && n.push(t.details.errorMessage), e.textContent = n.join(" | "), o.appendChild(e); } o.appendChild(i), o.appendChild(r), o.appendChild(l), c.appendChild(o), c.scrollTop = c.scrollHeight, n && s.set(n, o); } function clearLog() { c && (c.innerHTML = "", s.clear()); } function addInfoLog(e, t) { r || document.body.appendChild(createLogPanel()), addLogEntry(e, { type: "info" }, t); } function addSuccessLog(e, t) { r || document.body.appendChild(createLogPanel()), addLogEntry(e, { type: "success", details: t }); } function addErrorLog(e, t) { r || document.body.appendChild(createLogPanel()), addLogEntry(e, { type: "error", details: t }); } function formatNumberWithUnit(e) { return e >= 1e8 ? (e / 1e8).toFixed(0) + "E" : e >= 1e4 ? (e / 1e4).toFixed(0) + "W" : e.toString(); } const l = [ { key: "name", title: "\u8fbe\u4eba\u540d\u79f0" }, { key: "level", title: "\u7b49\u7ea7" }, { key: "fans_num", title: "\u7c89\u4e1d\u6570", format: function formatFansCount(e) { if (null == e) return ""; const t = 100 * Math.floor(e / 100); return t >= 1e4 ? (t / 1e4).toFixed(1) + "W" : t >= 1e3 ? (t / 1e3).toFixed(1) + "K" : t.toString(); } }, { key: "sale_range", title: "\u5e97\u94fa\u63a8\u5e7f\u9500\u552e\u989d", getValue: e => e, format: function formatSaleRange(e) { const t = e.sale?.low, n = e.sale?.high; return null == t || null == n ? "" : 0 === t && 0 === n ? "0" : t === n ? formatNumberWithUnit(t) : `${formatNumberWithUnit(t)}-${formatNumberWithUnit(n)}`; } }, { key: "live_num", title: "\u5173\u8054\u76f4\u64ad\u573a\u6b21" }, { key: "video_num", title: "\u5173\u8054\u77ed\u89c6\u9891\u6570" }, { key: "promotion_num", title: "\u63a8\u5e7f\u5546\u54c1\u6570" }, { key: "wechat_id", title: "Wechat" } ]; async function exportSelectedShops() { const e = Array.from(document.querySelectorAll('.shop-card-checkbox input[type="checkbox"]:checked')).map((e => e.closest(".shop-card"))).filter((e => null !== e)); if (0 === e.length) return void alert("\u8bf7\u5148\u9009\u62e9\u8981\u5bfc\u51fa\u7684\u8fbe\u4eba"); const t = confirm(`\u5df2\u9009\u4e2d ${e.length} \u4e2a\u8fbe\u4eba\uff0c\u662f\u5426\u8981\u53d1\u9001\u9080\u7ea6\uff1f`); if (t) { const e = getConfig(); if (!e.templates.length || !e.activeTemplateId) return void alert("\u8bf7\u5148\u914d\u7f6e\u9080\u7ea6\u6a21\u677f"); if (!e.productIds.length) return void alert("\u8bf7\u5148\u914d\u7f6e\u5546\u54c1"); if (!e.contactInfo.phone || !e.contactInfo.wechat) return void alert("\u8bf7\u5148\u914d\u7f6e\u8054\u7cfb\u65b9\u5f0f"); } clearLog(); const n = e.length; addInfoLog(`\u5f00\u59cb\u5904\u7406 | \u5171\u9009\u4e2d ${n} \u4e2a\u8fbe\u4eba`); const o = getShopProfilesFromElements(e); if (0 === o.length) return void addErrorLog("\u672a\u627e\u5230\u8fbe\u4eba\u6570\u636e"); let a = 0, r = 0, c = 0, s = 0, d = 0; const p = Date.now().toString(); addInfoLog("------------------------", p), addInfoLog("\u23f3 \u5904\u7406\u8fdb\u5ea6: 0%", p), addInfoLog("------------------------", p); const h = []; for (const i of o) { d++; try { const e = i.name || i.nickname || "\u672a\u77e5\u8fbe\u4eba"; let o = ""; const l = await queryContact(i); let u = `[${d}/${n}] ${e}`, g = []; if (200 !== l.code && 0 !== l.code || !l.data?.wechat_id) { r++; u += ` | \u274c \u67e5\u8be2\u5931\u8d25: ${l.message || "\u672a\u627e\u5230\u8054\u7cfb\u65b9\u5f0f"}`, "api" === l.source && void 0 !== l.remaining && g.push(`API:${l.remaining}`); } else a++, o = l.data.wechat_id, u += ` | \u2705 \u67e5\u8be2\u6210\u529f: ${o}`, "db" === l.source && l.saved_at && g.push(`DB:${formatDateTime(l.saved_at)}`), "api" === l.source && void 0 !== l.remaining && g.push(`API:${l.remaining}`); if (t) try { const e = convertConfigToRequestBody(i.sec_author_id), t = await sendInvite(e); 0 === t.code ? (c++, u += " | \u2705 \u9080\u7ea6\u6210\u529f") : (s++, u += ` | \u274c \u9080\u7ea6\u5931\u8d25: ${t.msg}`); } catch (f) { s++; u += ` | \u274c \u9080\u7ea6\u5931\u8d25: ${f.message}`; } g.length > 0 && (u += ` | ${g.join(" | ")}`), u.includes("\u274c") ? addErrorLog(u) : addSuccessLog(u); const m = Math.round(d / n * 100); addInfoLog(`\u23f3 \u5904\u7406\u8fdb\u5ea6: ${m}%\n\u67e5\u8be2\u8fdb\u5ea6: \u2705${a} \u274c${r}` + (t ? `\n\u9080\u7ea6\u8fdb\u5ea6: \u2705${c} \u274c${s}` : ""), p), h.push({ ...i, wechat_id: o }); } catch (u) { r++; const e = u.message; let o = `[${d}/${n}] ${i.name || i.nickname || "\u672a\u77e5\u8fbe\u4eba"} | \u274c \u67e5\u8be2\u5931\u8d25: ${e}`; if (t) try { const e = convertConfigToRequestBody(i.sec_author_id), t = await sendInvite(e); 0 === t.code ? (c++, o += " | \u2705 \u9080\u7ea6\u6210\u529f") : (s++, o += ` | \u274c \u9080\u7ea6\u5931\u8d25: ${t.msg}`); } catch (f) { s++; o += ` | \u274c \u9080\u7ea6\u5931\u8d25: ${f.message}`; } addErrorLog(o), h.push({ ...i, wechat_id: "" }); } } if (addInfoLog("------------------------"), addInfoLog(t ? `\u2728 \u5904\u7406\u5b8c\u6210 | \u67e5\u8be2\u6210\u529f\u7387: ${a}/${n} (${Math.round(a / n * 100)}%) | \u9080\u7ea6\u6210\u529f\u7387: ${c}/${n} (${Math.round(c / n * 100)}%)` : `\u2728 \u5904\u7406\u5b8c\u6210 | \u67e5\u8be2\u6210\u529f\u7387: ${a}/${n} (${Math.round(a / n * 100)}%)`), a > 0) { const e = (function convertToCSV(e) { const t = l.map((e => e.title)).join(","), n = e.map((e => l.map((t => { let n; if (t.getValue) n = t.getValue(e); else if (t.key.startsWith("sale_")) { const o = t.key.replace("sale_", ""); n = e.sale?.[o]; } else n = e[t.key]; return t.format ? formatValue(t.format(n)) : formatValue(n); })).join(","))); return [ t, ...n ].join("\n"); })(h), t = new Blob([ "\ufeff" + e ], { type: "text/csv;charset=utf-8;" }), n = URL.createObjectURL(t), o = document.createElement("a"); o.href = n; const {name: a} = (function getShopInfo() { return { ...i }; })(), r = (new Date).toISOString().split("T")[0], c = a ? `${a}_\u8fbe\u4eba\u6570\u636e_${r}.csv` : `\u8fbe\u4eba\u6570\u636e_${r}.csv`; o.download = c, document.body.appendChild(o), o.click(), document.body.removeChild(o), URL.revokeObjectURL(n), addSuccessLog("\u6587\u4ef6\u5bfc\u51fa\u5b8c\u6210"); } } function formatValue(e) { return null == e ? "" : "boolean" == typeof e ? e ? "\u662f" : "\u5426" : "number" == typeof e ? e.toString() : ("object" != typeof e || Array.isArray(e) || (e = JSON.stringify(e)), "string" == typeof e && (e.includes(",") || e.includes("\n") || e.includes('"')) ? `"${e.replace(/"/g, '""')}"` : String(e)); } const d = '', p = '', h = ''; function updateExportButtonText(e) { const t = document.querySelectorAll('.shop-card-checkbox input[type="checkbox"]:checked').length; e.innerHTML = `${p}\u5bfc\u51fa\u9009\u4e2d(${t})`; } const f = '', u = ''; function watchForElement(e, t) { document.querySelector(".shop-control-panel") || document.body.appendChild((function createControlPanel() { const e = document.createElement("div"); e.className = "shop-control-panel", e.style.cssText = "\n position: fixed;\n bottom: 0;\n right: 60px;\n background: white;\n padding: 16px;\n border-radius: 8px 8px 0 0;\n box-shadow: 0 2px 8px rgba(0,0,0,0.15);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n gap: 12px;\n font-size: 12px;\n "; const t = document.createElement("div"); t.style.cssText = "\n padding: 4px 8px;\n margin: -16px -16px 8px -16px;\n background: #fafafa;\n border-radius: 8px 8px 0 0;\n border-bottom: 1px solid #f0f0f0;\n font-weight: 500;\n color: #333;\n font-size: 13px;\n ", t.textContent = "\u6279\u91cf\u64cd\u4f5c"; const n = document.createElement("button"); n.innerHTML = `${d}\u5168\u9009`, n.style.cssText = "\n padding: 0 12px;\n height: 28px;\n background-color: #fff;\n color: #1890ff;\n border: 1px solid #1890ff;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.3s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n &:hover {\n background-color: #1890ff;\n color: #fff;\n }\n "; const o = document.createElement("button"); o.innerHTML = `${p}\u5bfc\u51fa\u9009\u4e2d(0)`, o.style.cssText = "\n padding: 0 12px;\n height: 28px;\n background-color: #52c41a;\n color: white;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.3s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n &:hover {\n background-color: #73d13d;\n }\n "; const i = document.createElement("button"); i.innerHTML = `${h}\u9080\u8bf7\u914d\u7f6e`, i.style.cssText = "\n padding: 0 12px;\n height: 28px;\n background-color: #f7f7f7;\n color: #666;\n border: 1px solid #d9d9d9;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.3s;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n &:hover {\n color: #40a9ff;\n border-color: #40a9ff;\n svg {\n fill: #40a9ff;\n }\n }\n "; const a = document.createElement("div"); a.style.cssText = "\n display: flex;\n flex-direction: column;\n gap: 8px;\n "; let r = !1; return n.addEventListener("click", (() => { r = !r, n.innerHTML = `${d}${r ? "\u53d6\u6d88\u5168\u9009" : "\u5168\u9009"}`, document.querySelectorAll('.shop-card-checkbox input[type="checkbox"]').forEach((e => { e.checked = r; })), updateExportButtonText(o); })), o.addEventListener("click", exportSelectedShops), i.addEventListener("click", showConfigPanel), document.addEventListener("checkbox-change", (() => { updateExportButtonText(o); })), a.appendChild(n), a.appendChild(o), a.appendChild(i), e.appendChild(t), e.appendChild(a), e; })()), document.querySelector(".shop-log-panel") || document.body.appendChild(createLogPanel()); const n = document.body; new MutationObserver((() => { document.querySelectorAll(e).forEach((e => { e.querySelector(".shop-card-checkbox") || t(e); })); })).observe(n, { childList: !0, subtree: !0 }); document.querySelectorAll(e).forEach((e => { e.querySelector(".shop-card-checkbox") || t(e); })); } function handleShopCard(e) { const t = (function createCheckboxDiv() { const e = document.createElement("div"); e.className = "shop-card-checkbox", e.style.cssText = "\n display: flex;\n align-items: center;\n padding: 0 10px;\n margin-right: 10px;\n "; const t = document.createElement("input"); return t.type = "checkbox", t.style.cssText = "\n width: 16px;\n height: 16px;\n cursor: pointer;\n ", t.addEventListener("change", (e => { e.stopPropagation(), e.target.checked, document.dispatchEvent(new CustomEvent("checkbox-change")); })), t.addEventListener("click", (e => { e.stopPropagation(); })), e.appendChild(t), e; })(), n = (function createActionButton(e) { const t = document.createElement("div"); t.style.cssText = "\n display: flex;\n gap: 8px;\n margin-left: 10px;\n "; const n = document.createElement("button"); n.innerHTML = `${f}\u67e5\u8be2`; const o = `${f}\u67e5\u8be2`, i = `${f}\u67e5\u8be2\u4e2d...`; n.style.cssText = "\n padding: 0 12px;\n font-size: 12px;\n border-radius: 4px;\n cursor: pointer;\n border: 1px solid #1890ff;\n background-color: #fff;\n color: #1890ff;\n transition: all 0.3s;\n outline: none;\n font-weight: normal;\n height: 24px;\n line-height: 22px;\n box-shadow: 0 2px 0 rgba(0,0,0,0.015);\n white-space: nowrap;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 48px;\n "; const a = document.createElement("button"); a.innerHTML = `${u}\u9080\u7ea6`; const r = `${u}\u9080\u7ea6`, c = `${u}\u53d1\u9001\u4e2d...`; a.style.cssText = "\n padding: 0 12px;\n font-size: 12px;\n border-radius: 4px;\n cursor: pointer;\n border: 1px solid #52c41a;\n background-color: #52c41a;\n color: #fff;\n transition: all 0.3s;\n outline: none;\n font-weight: normal;\n height: 24px;\n line-height: 22px;\n box-shadow: 0 2px 0 rgba(0,0,0,0.015);\n white-space: nowrap;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 64px;\n "; const setButtonDisabled = (e, t) => { t ? (e.style.opacity = "0.65", e.style.cursor = "not-allowed", e.disabled = !0) : (e.style.opacity = "1", e.style.cursor = "pointer", e.disabled = !1); }; return n.addEventListener("mouseover", (() => { n.disabled || (n.style.backgroundColor = "#40a9ff", n.style.borderColor = "#40a9ff", n.style.color = "#fff"); })), n.addEventListener("mouseout", (() => { n.disabled || (n.style.backgroundColor = "#fff", n.style.borderColor = "#1890ff", n.style.color = "#1890ff"); })), a.addEventListener("mouseover", (() => { a.disabled || (a.style.backgroundColor = "#73d13d", a.style.borderColor = "#73d13d"); })), a.addEventListener("mouseout", (() => { a.disabled || (a.style.backgroundColor = "#52c41a", a.style.borderColor = "#52c41a"); })), n.addEventListener("mousedown", (() => { n.disabled || (n.style.backgroundColor = "#096dd9", n.style.borderColor = "#096dd9"); })), n.addEventListener("mouseup", (() => { n.disabled || (n.style.backgroundColor = "#40a9ff", n.style.borderColor = "#40a9ff"); })), a.addEventListener("mousedown", (() => { a.disabled || (a.style.backgroundColor = "#389e0d", a.style.borderColor = "#389e0d"); })), a.addEventListener("mouseup", (() => { a.disabled || (a.style.backgroundColor = "#73d13d", a.style.borderColor = "#73d13d"); })), n.addEventListener("click", (async t => { if (!n.disabled) { t.stopPropagation(), t.preventDefault(); try { setButtonDisabled(n, !0), n.innerHTML = i; const t = getShopProfileFromElement(e); if (!t) return void alert("\u672a\u627e\u5230\u8fbe\u4eba\u8d44\u6599"); const o = await queryContact(t); if (200 !== o.code && 0 !== o.code || !o.data?.wechat_id) alert(`\u67e5\u8be2\u5931\u8d25: ${o.message || "\u672a\u627e\u5230\u8054\u7cfb\u65b9\u5f0f"}`); else { const e = [ `\u8fbe\u4eba\u540d\u79f0: ${t.name || t.nickname || "\u672a\u77e5"}`, `\u8054\u7cfb\u65b9\u5f0f: ${o.data.wechat_id}`, "\u6570\u636e\u6765\u6e90: " + ("db" === o.source ? "\u6570\u636e\u5e93" : "API\u67e5\u8be2"), o.remaining ? `API\u5269\u4f59\u6b21\u6570: ${o.remaining}` : "", "db" === o.source && o.saved_at ? `\u6570\u636e\u5e93\u66f4\u65b0\u65f6\u95f4: ${formatDateTime(o.saved_at)}` : "" ].filter(Boolean).join("\n"); alert(e); } } catch (a) { alert("\u67e5\u8be2\u8054\u7cfb\u65b9\u5f0f\u5931\u8d25: " + a.message); } finally { setButtonDisabled(n, !1), n.innerHTML = o; } } })), a.addEventListener("click", (async t => { if (!a.disabled) { t.stopPropagation(), t.preventDefault(); try { setButtonDisabled(a, !0), a.innerHTML = c; const t = getShopProfileFromElement(e); if (!t) return void alert("\u672a\u627e\u5230\u8fbe\u4eba\u8d44\u6599"); const n = getConfig(); if (!n.templates.length || !n.activeTemplateId) return void alert("\u8bf7\u5148\u914d\u7f6e\u9080\u7ea6\u6a21\u677f"); if (!n.productIds.length) return void alert("\u8bf7\u5148\u914d\u7f6e\u5546\u54c1"); if (!n.contactInfo.phone || !n.contactInfo.wechat) return void alert("\u8bf7\u5148\u914d\u7f6e\u8054\u7cfb\u65b9\u5f0f"); const o = convertConfigToRequestBody(t.sec_author_id), i = await sendInvite(o); 0 === i.code ? alert("\u9080\u7ea6\u53d1\u9001\u6210\u529f\uff01") : alert(`\u9080\u7ea6\u53d1\u9001\u5931\u8d25: ${i.msg}`); } catch (n) { alert("\u53d1\u9001\u9080\u7ea6\u5931\u8d25: " + n.message); } finally { setButtonDisabled(a, !1), a.innerHTML = r; } } })), t.appendChild(n), t.appendChild(a), t; })(e); e.insertBefore(t, e.firstChild), e.appendChild(n); } watchForElement(".shop-card", handleShopCard), (function setupApiMonitor() { window.addEventListener("load", (function() { const e = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(t, a, r, c, s) { return "string" == typeof a && (a.includes("/square_pc_api/shop/shopProfileAuthorList") ? this.addEventListener("load", (function() { try { const e = JSON.parse(this.response), t = this.responseURL; n[t] = e, e.data?.author_list?.forEach((e => { e.avatar && (o[e.avatar] = t); })); } catch (e) {} })) : a.includes("/square_pc_api/shop/shopProfile") && this.addEventListener("load", (function() { try { const e = JSON.parse(this.response); if (0 === e.code && e.data?.basic_info) { const {basic_info: t} = e.data; i.name = t.name || "", i.avatar = t.avatar || "", i.shopId = t.shop_id?.toString() || ""; } } catch (e) {} }))), e.apply(this, [ t, a, r ?? !0, c, s ]); }; })); })(); })();