您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在当前页面插入悬浮元素,点击展开窗口并发送请求,将结果展示在表格中并提供Excel下载按钮
// ==UserScript== // @name qjjtools // @namespace npm/vite-plugin-monkey // @version 10.0.0 // @icon https://vitejs.dev/logo.svg // @match *://*/* // @require https://cdnjs.cloudflare.com/ajax/libs/vue/3.5.18/vue.global.prod.min.js // @require data:application/javascript,%3Bwindow.Vue%3DVue%3B // @require https://cdnjs.cloudflare.com/ajax/libs/naive-ui/2.42.0/index.prod.js // @require data:application/javascript,%3Bwindow.naive%3Dnaive%3B // @grant GM_addStyle // @description 在当前页面插入悬浮元素,点击展开窗口并发送请求,将结果展示在表格中并提供Excel下载按钮 // ==/UserScript== (a=>{if(typeof GM_addStyle=="function"){GM_addStyle(a);return}const d=document.createElement("style");d.textContent=a,document.head.append(d)})(" [data-v-303426f9] .n-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0}[data-v-303426f9] .n-modal-mask{background-color:#0006}[data-v-303426f9] .n-modal-content{border-radius:8px;overflow:hidden}.n-progress[data-v-29be6a47],.n-progress[data-v-8edd34a0]{margin:10px 0}.createrplan-container[data-v-5dbab58c]{padding:24px;max-width:1000px;margin:0 auto;background:linear-gradient(135deg,#667eea,#764ba2);min-height:100vh}.main-card[data-v-5dbab58c]{background:#fffffff2;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:16px;box-shadow:0 8px 32px #0000001a;border:1px solid rgba(255,255,255,.2)}.main-card[data-v-5dbab58c] .n-card-header{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border-radius:16px 16px 0 0;padding:20px 24px}.main-card[data-v-5dbab58c] .n-card-content{padding:24px}[data-v-5dbab58c] .n-button{border-radius:12px;font-weight:500;transition:all .3s ease}[data-v-5dbab58c] .n-button:hover{transform:translateY(-2px);box-shadow:0 4px 16px #00000026}[data-v-5dbab58c] .n-input{border-radius:8px}[data-v-5dbab58c] .n-form-item-label{font-weight:500;color:#333}[data-v-5dbab58c] .n-tag{border-radius:20px;font-weight:500}.button-container[data-v-aaaae17f]{padding:20px}@media (max-width: 768px){.button-container[data-v-aaaae17f] .n-space{flex-direction:column!important}.button-container[data-v-aaaae17f] .n-button{width:100%!important;margin:4px 0!important}}.auto-height-card[data-v-aaaae17f],.auto-height-card[data-v-aaaae17f] .n-card__content{flex:1;display:flex;flex-direction:column}.flex-card[data-v-aaaae17f]{flex:2}.default-component[data-v-ff0a68db]{display:flex;justify-content:center;align-items:center;height:100%;padding:20px}.jihua-container[data-v-f7d071d3]{padding:20px;max-width:800px;margin:0 auto}.description[data-v-f7d071d3]{background-color:#f5f5f5;padding:12px;border-radius:4px;margin-bottom:16px}.description pre[data-v-f7d071d3]{background-color:#fff;padding:8px;border-radius:4px;margin:8px 0;white-space:pre-wrap}.plan-container[data-v-f977d1aa]{padding:20px;max-width:800px;margin:0 auto}.description[data-v-f977d1aa]{background-color:#f5f5f5;padding:12px;border-radius:4px;margin-bottom:16px}.description pre[data-v-f977d1aa]{background-color:#fff;padding:8px;border-radius:4px;margin:8px 0;white-space:pre-wrap}.button-container[data-v-c6e92986]{padding:20px}.kuaishou-container[data-v-7227acb7]{padding:24px;max-width:1000px;margin:0 auto;background:linear-gradient(135deg,#667eea,#764ba2);min-height:100vh}.tool-card[data-v-7227acb7]{background:#fffffff2;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:16px;box-shadow:0 8px 32px #0000001a;border:1px solid rgba(255,255,255,.2)}.tool-card[data-v-7227acb7] .n-card-header{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border-radius:16px 16px 0 0;padding:20px 24px}.tool-card[data-v-7227acb7] .n-card-content{padding:24px}[data-v-7227acb7] .n-button{border-radius:12px;font-weight:500;transition:all .3s ease}[data-v-7227acb7] .n-button:hover{transform:translateY(-2px);box-shadow:0 4px 16px #00000026}[data-v-7227acb7] .n-input{border-radius:8px}[data-v-7227acb7] .n-form-item-label{font-weight:500;color:#333}[data-v-7227acb7] .n-collapse,[data-v-7227acb7] .n-table{border-radius:8px;overflow:hidden} "); (function (vue, naive) { 'use strict'; var __getOwnPropNames = Object.getOwnPropertyNames; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var require_main_001 = __commonJS({ "main-DGUFX1JG.js"(exports, module) { class LinkChecker { constructor() { this.isLoading = false; this.tableData = []; this.responseData = []; this.stats = { totalCreativity: 0, clickUrlCounts: [], expoUrlCounts: [] }; } // 检查链接的主要方法 async checkLinks() { this.isLoading = true; this.clearData(); try { const allData = await this.fetchAllData(); this.responseData = allData; this.tableData = allData; this.processStats(allData); console.log("读取成功"); return { success: true, data: allData }; } catch (error) { console.error("请求或处理数据时出错:", error); return { success: false, error: error.message }; } finally { this.isLoading = false; } } // 获取所有数据 async fetchAllData() { let maxPageNum = 4; let pageNum = 1; let totalPage = 1; let allData = []; do { const headers = this.getHeaders(); const response = await fetch( `https://ad.xiaohongshu.com/api/leona/rtb/creativity/list?pageNum=${pageNum}&pageSize=50`, { method: "POST", headers, body: JSON.stringify({ startTime: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], endTime: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], pageNum, pageSize: 50 }) } ); const data = await response.json(); if (data && data.data && data.data.list) { allData = allData.concat(data.data.list); totalPage = data.data.totalPage; } else { throw new Error("API 返回数据格式不正确"); } pageNum++; } while (pageNum <= totalPage && pageNum <= maxPageNum); return allData; } // 获取请求头 getHeaders() { const headers = { accept: "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json;charset=UTF-8", priority: "u=1, i", "sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", Referer: location.href, Origin: location.origin, "User-Agent": navigator.userAgent }; if (location.href.indexOf("vSellerId") !== -1) { headers["v-seller-id"] = location.search.match( new RegExp("(?<=vSellerId=)[0-9a-z].*", "g") ); } return headers; } // 处理统计数据 processStats(data) { this.stats.totalCreativity = new Set( data.map((item) => item.creativityId) ).size; const groupCountByField = (data2, field) => { const map = {}; data2.forEach((item) => { if (Array.isArray(item[field])) { item[field].forEach((url) => { if (!url) return; map[url] = (map[url] || 0) + 1; }); } }); return Object.entries(map).map(([url, count]) => ({ url, count, displayUrl: this.ellipsisUrl(url) })); }; this.stats.clickUrlCounts = groupCountByField(data, "clickUrls"); this.stats.expoUrlCounts = groupCountByField(data, "expoUrls"); } // URL 缩略 ellipsisUrl(url, head = 30, tail = 30) { if (url.length <= head + tail + 3) return url; return url.slice(0, head) + "..." + url.slice(-tail); } // 提取 URL 参数 extractUrlParam(url) { if (!url) return ""; const match = url.match(/https:\/\/magellan\.alimama\.com\/(.*?)&/); return match ? match[1] : url; } // 清空数据 clearData() { this.tableData = []; this.responseData = []; this.stats = { totalCreativity: 0, clickUrlCounts: [], expoUrlCounts: [] }; } // 下载数据为 CSV downloadCSV() { if (this.responseData.length === 0) { console.log("没有可下载的数据!"); return; } const BOM = "\uFEFF"; const headers = [ "创建时间", "创意名", "创意ID", "点击链接", "曝光链接", "笔记id" ]; const csvContent = [headers.join(",")]; this.responseData.forEach((item) => { const createTime = item.creativityCreateTime || ""; const creativityName = item.creativityName || ""; const creativityId = item.creativityId || ""; const clickUrl = JSON.stringify(item.clickUrls) || ""; const expoUrl = JSON.stringify(item.expoUrls) || ""; const noteId = item.noteId + "" || ""; const escapeCsvValue = (value) => { if (typeof value !== "string") return value; if (value.includes(",") || value.includes('"') || value.includes("\n")) { return `"${value.replace(/"/g, '""')}"`; } return value; }; const values = [ createTime, creativityName, creativityId, clickUrl, expoUrl, noteId ].map(escapeCsvValue); csvContent.push(values.join(",")); }); const csv = BOM + csvContent.join("\n"); const blob = new Blob([csv], { type: "text/csv;charset=utf-8" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); const timestamp = (/* @__PURE__ */ new Date()).toLocaleString().replace(/[/:]/g, "-"); link.setAttribute("href", url); link.setAttribute("download", `data_${timestamp}.csv`); document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } // 获取当前状态 getState() { return { isLoading: this.isLoading, tableData: this.tableData, stats: this.stats, hasData: this.responseData.length > 0 }; } } if (typeof module !== "undefined" && module.exports) { module.exports = LinkChecker; } else if (typeof window !== "undefined") { window.LinkChecker = LinkChecker; } async function reanmeSend(id, name) { const headers = { accept: "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json;charset=UTF-8", priority: "u=1, i", "sec-ch-ua": '"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"macOS"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "x-b3-traceid": "dee287ce9b6526cc" }; if (location.href.indexOf("vSellerId") != -1) { headers["v-seller-id"] = location.search.match(new RegExp("(?<=vSellerId=)[0-9a-z].*", "g")); } return fetch( "https://ad.xiaohongshu.com/api/leona/rtb/creativity/batch/update/name", { headers, referrerPolicy: "strict-origin-when-cross-origin", body: `{"creativityId":${id},"creativityName":"${name}"}`, method: "POST", mode: "cors", credentials: "include" } ); } async function mainSend(old1, new1, onProgress) { const n = location.href.match(/[0-9]{1,20}/g); const headers = { accept: "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json;charset=UTF-8", priority: "u=1, i", "sec-ch-ua": '"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"macOS"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin" }; if (location.href.indexOf("vSellerId") != -1) { headers["v-seller-id"] = location.search.match(new RegExp("(?<=vSellerId=)[0-9a-z].*", "g")); } const r = await fetch( "https://ad.xiaohongshu.com/api/leona/rtb/creativity/list", { headers, referrerPolicy: "strict-origin-when-cross-origin", body: `{"campaignId":${n[0]},"unitId":${n[1]},"startTime":"${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}","endTime":"${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}","pageNum":1,"pageSize":50}`, method: "POST", mode: "cors", credentials: "include" } ); const j = await r.json(); const creativeList = j.data.list; const total = creativeList.length; if (onProgress) { onProgress(0, 0, total); } for (let i = 0; i < total; i++) { const element = creativeList[i]; const newName = element.creativityName.replace(new RegExp(old1, "g"), new1); await reanmeSend(element.creativityId, newName); if (onProgress) { const progress = (i + 1) / total * 100; onProgress(Math.round(progress), i + 1, total); } } } const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const _sfc_main$a = { __name: "rename", setup(__props) { const message = naive.useMessage(); const isRenaming = vue.ref(false); const renameOldChar = vue.ref(""); const renameNewChar = vue.ref(""); const renameProgress = vue.ref(0); const currentProgress = vue.ref(0); const totalProgress = vue.ref(0); const progressText = vue.computed(() => { if (totalProgress.value > 0) { return `正在处理: ${currentProgress.value}/${totalProgress.value} (${renameProgress.value}%)`; } return "正在处理中..."; }); async function handleRename() { if (!renameOldChar.value) { message.warning("请输入要被替换的旧字符"); return; } isRenaming.value = true; renameProgress.value = 0; currentProgress.value = 0; totalProgress.value = 0; try { await mainSend(renameOldChar.value, renameNewChar.value, (progress, current, total) => { renameProgress.value = progress; currentProgress.value = current; totalProgress.value = total; }); message.success("批量重命名操作已完成!"); renameOldChar.value = ""; renameNewChar.value = ""; } catch (error) { message.error("重命名过程中发生错误"); console.error(error); } finally { isRenaming.value = false; } } function cancelRename() { renameOldChar.value = ""; renameNewChar.value = ""; renameProgress.value = 0; currentProgress.value = 0; totalProgress.value = 0; } return (_ctx, _cache) => { const _component_n_input = vue.resolveComponent("n-input"); const _component_n_progress = vue.resolveComponent("n-progress"); const _component_n_text = vue.resolveComponent("n-text"); const _component_n_space = vue.resolveComponent("n-space"); const _component_n_button = vue.resolveComponent("n-button"); const _component_n_modal = vue.resolveComponent("n-modal"); return vue.openBlock(), vue.createBlock(_component_n_modal, { preset: "card", style: { "width": "500px" }, title: "修改单元内计划字符", show: true, "mask-closable": false, "close-on-esc": false, "transform-origin": "center", closable: "" }, { footer: vue.withCtx(() => [ vue.createVNode(_component_n_button, { onClick: cancelRename }, { default: vue.withCtx(() => _cache[2] || (_cache[2] = [ vue.createTextVNode("取消", -1) ])), _: 1, __: [2] }), vue.createVNode(_component_n_button, { type: "primary", onClick: handleRename, loading: isRenaming.value, style: { "margin-left": "12px" } }, { default: vue.withCtx(() => _cache[3] || (_cache[3] = [ vue.createTextVNode("确认替换", -1) ])), _: 1, __: [3] }, 8, ["loading"]) ]), default: vue.withCtx(() => [ vue.createVNode(_component_n_space, { vertical: "" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: renameOldChar.value, "onUpdate:value": _cache[0] || (_cache[0] = ($event) => renameOldChar.value = $event), placeholder: "输入要被替换的旧字符" }, null, 8, ["value"]), vue.createVNode(_component_n_input, { value: renameNewChar.value, "onUpdate:value": _cache[1] || (_cache[1] = ($event) => renameNewChar.value = $event), placeholder: "输入用于替换的新字符" }, null, 8, ["value"]), isRenaming.value ? (vue.openBlock(), vue.createBlock(_component_n_progress, { key: 0, type: "line", percentage: renameProgress.value, "indicator-placement": "inside", processing: "" }, null, 8, ["percentage"])) : vue.createCommentVNode("", true), isRenaming.value ? (vue.openBlock(), vue.createBlock(_component_n_text, { key: 1, depth: "3", style: { "text-align": "center" } }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(progressText.value), 1) ]), _: 1 })) : vue.createCommentVNode("", true) ]), _: 1 }) ]), _: 1 }); }; } }; const rename = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-303426f9"]]); const _sfc_main$9 = { __name: "BatchPrice", props: { show: { type: Boolean, default: false } }, emits: ["update:show"], setup(__props, { emit: __emit }) { const props = __props; const emit = __emit; const message = naive.useMessage(); const formRef = vue.ref(null); const showModal = vue.ref(false); const showProgress = vue.ref(false); const loading = vue.ref(false); const progress = vue.ref(0); const progressInfo = vue.ref(""); const formValue = vue.reactive({ mode: "all", // all 或 uid price: null, unitIds: "" }); const modeOptions = [ { label: "全部调价", value: "all" }, { label: "指定单元ID调价", value: "uid" } ]; const rules = { mode: { required: true, message: "请选择调价模式", trigger: "change" }, price: { required: true, validator(rule, value) { if (!value && value !== 0) { return new Error("请输入调整价格"); } else if (value < 0) { return new Error("价格不能为负数"); } return true; }, trigger: ["input", "blur"] }, unitIds: { trigger: ["input", "blur"], validator(rule, value) { if (formValue.mode === "uid") { if (!value) { return new Error("请输入单元ID列表"); } const ids = value.trim().split(/\s+/); if (ids.length === 0) { return new Error("请输入有效的单元ID"); } } return true; } } }; vue.watch( () => props.show, (newVal) => { showModal.value = newVal; } ); vue.watch(showModal, (newVal) => { emit("update:show", newVal); }); const handleModeChange = (value) => { formValue.mode = value; }; const closeModal = () => { showModal.value = false; formRef.value?.restoreValidation(); }; const getCurrentTimestamp = () => { return Math.floor(Date.now() / 1e3); }; const processUnitData = (body, bid) => { body.removeBind = 0; body.sourceFlag = "web"; body.pageEnterTime = getCurrentTimestamp() - 10; body.pageSubmitTime = getCurrentTimestamp(); if (body.keywordWithBid && Array.isArray(body.keywordWithBid)) { body.keywordWithBid.forEach((item) => { item.bid = bid * 100; }); } return body; }; const updateUnitData = async (body) => { const requiredFields = [ "sourceFlag", "unitId", "unitName", "promotionTarget", "keywordWithBid", "targetConfig", "phraseMatchTypeUpgrade", "removeBind", "noteIds", "keywordGenType", "pageEnterTime", "pageSubmitTime" ]; const filteredBody = {}; requiredFields.forEach((key) => { if (body.hasOwnProperty(key)) { if (key === "pageEnterTime" || key === "pageSubmitTime") { const timestamp = body[key]; if (typeof timestamp === "number" && timestamp.toString().length === 10) { filteredBody[key] = timestamp * 1e3; } else { filteredBody[key] = timestamp; } } else { filteredBody[key] = body[key]; } } }); filteredBody.keywordGenType = 0; const ntime = Date.now(); filteredBody.pageSubmitTime = ntime; const headers = { "accept": "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json", "priority": "u=1, i", "sec-ch-ua": '"Not;A=Brand";v="99", "Microsoft Edge";v="139", "Chromium";v="139"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"macOS"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "x-t": ntime }; if (location.href.indexOf("vSellerId") !== -1) { headers["v-seller-id"] = location.search.match(new RegExp("(?<=vSellerId=)[0-9a-z].*", "g")); } try { const response = await fetch("https://ad.xiaohongshu.com/api/leona/rtb/unit", { headers, referrerPolicy: "strict-origin-when-cross-origin", body: JSON.stringify(filteredBody), method: "PUT", mode: "cors", credentials: "include" }); const result = await response.json(); return result; } catch (error) { console.error("请求出错:", error); throw error; } }; const fetchUnitList = async () => { const headers = { accept: "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json", priority: "u=1, i", "sec-ch-ua": '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin" }; if (location.href.indexOf("vSellerId") !== -1) { headers["v-seller-id"] = location.search.match(new RegExp("(?<=vSellerId=)[0-9a-z].*", "g")); } let data = []; let pageNum = 1; let totalPage = 1; do { const response = await fetch( "https://ad.xiaohongshu.com/api/leona/rtb/unit/search", { headers, referrer: "https://ad.xiaohongshu.com/aurora/ad/manage/creativity", referrerPolicy: "strict-origin-when-cross-origin", body: JSON.stringify({ startTime: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], endTime: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], pageNum, pageSize: 100, placementList: [2] }), method: "POST", mode: "cors", credentials: "include" } ); const result = await response.json(); data = data.concat(result.data.list); totalPage = result.data.totalPage; pageNum++; } while (pageNum <= totalPage); return data; }; const filterUnits = (allUnits, unitIds) => { const ids = unitIds.trim().split(/\s+/); return allUnits.filter((unit) => ids.includes(String(unit.unitId))); }; const handleSubmit = (e) => { e.preventDefault(); formRef.value?.validate(async (errors) => { if (!errors) { loading.value = true; showProgress.value = true; progress.value = 0; progressInfo.value = "正在获取单元数据..."; try { const allUnits = await fetchUnitList(); message.info(`获取到 ${allUnits.length} 个单元`); let targetUnits = []; if (formValue.mode === "all") { targetUnits = allUnits; } else { targetUnits = filterUnits(allUnits, formValue.unitIds); message.info(`筛选出 ${targetUnits.length} 个指定单元`); } const results = []; for (let i = 0; i < targetUnits.length; i++) { const unit = targetUnits[i]; progress.value = Math.round((i + 1) / targetUnits.length * 100); progressInfo.value = `正在调整单元: ${unit.unitName} (${i + 1}/${targetUnits.length})`; try { const processedData = processUnitData({ ...unit }, formValue.price); const result = await updateUnitData(processedData); results.push({ unitName: unit.unitName, unitId: unit.unitId, success: result.msg === "成功", message: result.msg }); await new Promise((resolve) => setTimeout(resolve, 700)); } catch (error) { results.push({ unitName: unit.unitName, unitId: unit.unitId, success: false, message: error.message || "请求失败" }); } } const successCount = results.filter((r) => r.success).length; message.success(`调整完成!成功: ${successCount}/${results.length}`); console.log("调价结果:", results); showModal.value = false; } catch (error) { message.error("操作失败: " + (error.message || "未知错误")); console.error("调价过程中出错:", error); } finally { loading.value = false; showProgress.value = false; } } else { message.error("请检查表单填写是否正确"); } }); }; return (_ctx, _cache) => { const _component_n_select = vue.resolveComponent("n-select"); const _component_n_form_item = vue.resolveComponent("n-form-item"); const _component_n_input_number = vue.resolveComponent("n-input-number"); const _component_n_input = vue.resolveComponent("n-input"); const _component_n_form = vue.resolveComponent("n-form"); const _component_n_button = vue.resolveComponent("n-button"); const _component_n_space = vue.resolveComponent("n-space"); const _component_n_modal = vue.resolveComponent("n-modal"); const _component_n_text = vue.resolveComponent("n-text"); const _component_n_progress = vue.resolveComponent("n-progress"); return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [ vue.createVNode(_component_n_modal, { show: showModal.value, "onUpdate:show": _cache[3] || (_cache[3] = ($event) => showModal.value = $event), preset: "card", style: { "width": "600px" }, title: "批量调整出价", "mask-closable": false, "close-on-esc": false }, { footer: vue.withCtx(() => [ vue.createVNode(_component_n_space, { justify: "end" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { onClick: closeModal }, { default: vue.withCtx(() => _cache[5] || (_cache[5] = [ vue.createTextVNode("取消", -1) ])), _: 1, __: [5] }), vue.createVNode(_component_n_button, { type: "primary", onClick: handleSubmit, loading: loading.value }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(loading.value ? "调整中..." : "确认调整"), 1) ]), _: 1 }, 8, ["loading"]) ]), _: 1 }) ]), default: vue.withCtx(() => [ vue.createVNode(_component_n_form, { model: formValue, rules, ref_key: "formRef", ref: formRef }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_form_item, { label: "调价模式", path: "mode" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_select, { value: formValue.mode, "onUpdate:value": [ _cache[0] || (_cache[0] = ($event) => formValue.mode = $event), handleModeChange ], options: modeOptions }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_form_item, { label: "调整价格", path: "price" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input_number, { value: formValue.price, "onUpdate:value": _cache[1] || (_cache[1] = ($event) => formValue.price = $event), "show-button": false, placeholder: "请输入要调整的价格", style: { "width": "100%" } }, null, 8, ["value"]) ]), _: 1 }), vue.withDirectives(vue.createVNode(_component_n_form_item, { label: "单元ID列表", path: "unitIds" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: formValue.unitIds, "onUpdate:value": _cache[2] || (_cache[2] = ($event) => formValue.unitIds = $event), type: "textarea", placeholder: "请输入单元ID,每行一个", autosize: { minRows: 3, maxRows: 6 } }, null, 8, ["value"]) ]), _: 1 }, 512), [ [vue.vShow, formValue.mode === "uid"] ]) ]), _: 1 }, 8, ["model"]) ]), _: 1 }, 8, ["show"]), vue.createVNode(_component_n_modal, { show: showProgress.value, "onUpdate:show": _cache[4] || (_cache[4] = ($event) => showProgress.value = $event), preset: "card", style: { "width": "500px" }, title: "调整进度", "mask-closable": false, "close-on-esc": false }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_space, { vertical: "" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_text, null, { default: vue.withCtx(() => _cache[6] || (_cache[6] = [ vue.createTextVNode("正在调整出价,请稍候...", -1) ])), _: 1, __: [6] }), vue.createVNode(_component_n_progress, { type: "line", percentage: progress.value, "indicator-placement": "inside", processing: "" }, null, 8, ["percentage"]), vue.createVNode(_component_n_text, { depth: "3" }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(progressInfo.value), 1) ]), _: 1 }) ]), _: 1 }) ]), _: 1 }, 8, ["show"]) ], 64); }; } }; const BatchPrice = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-29be6a47"]]); const _sfc_main$8 = { __name: "setplan", props: { show: { type: Boolean, default: false } }, emits: ["update:show"], setup(__props, { emit: __emit }) { const props = __props; const emit = __emit; const message = naive.useMessage(); const formRef = vue.ref(null); const showModal = vue.ref(false); const showProgress = vue.ref(false); const loading = vue.ref(false); const progress = vue.ref(0); const progressInfo = vue.ref(""); const progressDetail = vue.ref(""); const formValue = vue.reactive({ searchType: "creativeId", // creativeId, name, noteId actionType: "2", // 1: 开启, 2: 关闭 inputContent: "" }); const searchTypeOptions = [ { label: "创意ID", value: "creativeId" }, { label: "文字匹配", value: "name" }, { label: "笔记ID", value: "noteId" } ]; const actionTypeOptions = [ { label: "关闭", value: "2" }, { label: "开启", value: "1" } ]; const rules = { searchType: { required: true, message: "请选择搜索方式", trigger: "change" }, actionType: { required: true, message: "请选择操作类型", trigger: "change" }, inputContent: { required: true, trigger: ["input", "blur"], validator(rule, value) { if (!value) { return new Error("请输入内容"); } const lines = value.trim().split(/\r?\n/).filter((line) => line.trim() !== ""); if (lines.length === 0) { return new Error("请输入有效内容"); } return true; } } }; vue.watch( () => props.show, (newVal) => { showModal.value = newVal; } ); vue.watch(showModal, (newVal) => { emit("update:show", newVal); }); const closeModal = () => { showModal.value = false; formRef.value?.restoreValidation(); }; const chunkArray = (array, chunkSize) => { const chunks = []; for (let i = 0; i < array.length; i += chunkSize) { chunks.push(array.slice(i, i + chunkSize)); } return chunks; }; const toggleCreativePlan = async (chunkedIds, actionType) => { const actionText = actionType === "1" ? "开启" : "关闭"; const headers = { accept: "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json;charset=UTF-8", priority: "u=1, i", "sec-ch-ua": '"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"macOS"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin" }; if (location.href.indexOf("vSellerId") !== -1) { headers["v-seller-id"] = location.search.match(new RegExp("(?<=vSellerId=)[0-9a-z].*", "g")); } for (let i = 0; i < chunkedIds.length; i++) { const ids = chunkedIds[i]; let retry = true; let attempts = 0; const maxAttempts = 3; progress.value = Math.round((i + 1) / chunkedIds.length * 100); progressInfo.value = `正在${actionText}创意... (${i + 1}/${chunkedIds.length})`; progressDetail.value = `正在处理ID: [${ids.join(", ")}]`; while (retry && attempts < maxAttempts) { try { const response = await fetch( "https://ad.xiaohongshu.com/api/leona/rtb/creativity/batch/status", { headers, referrer: "https://ad.xiaohongshu.com/aurora/ad/manage/creativity", referrerPolicy: "strict-origin-when-cross-origin", body: JSON.stringify({ ids, actionType: parseInt(actionType) }), method: "PUT", mode: "cors", credentials: "include" } ); const result = await response.json(); if (result.msg === "成功") { message.success(`${actionText}创意成功: ${JSON.stringify(ids)}`); retry = false; } else { attempts++; if (attempts >= maxAttempts) { message.error(`${actionText}创意失败: ${result.msg}, ID: ${JSON.stringify(ids)}`); retry = false; } else { await new Promise((resolve) => setTimeout(resolve, 500)); } } } catch (error) { attempts++; if (attempts >= maxAttempts) { message.error(`${actionText}创意出错: ${error.message}, ID: ${JSON.stringify(ids)}`); retry = false; } else { await new Promise((resolve) => setTimeout(resolve, 500)); } } } } }; const toggleCreativeByNoteOrName = async (inputList, actionType, searchType) => { const headers = { accept: "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json;charset=UTF-8", priority: "u=1, i", "sec-ch-ua": '"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"macOS"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin" }; if (location.href.indexOf("vSellerId") !== -1) { headers["v-seller-id"] = location.search.match(new RegExp("(?<=vSellerId=)[0-9a-z].*", "g")); } for (let index = 0; index < inputList.length; index++) { const inputItem = inputList[index]; progress.value = Math.round((index + 1) / inputList.length * 100); progressInfo.value = `正在处理: ${inputItem} (${index + 1}/${inputList.length})`; try { let searchValue = inputItem; let placementList = null; if (inputItem.indexOf(" ") !== -1) { const parts = inputItem.split(" "); searchValue = parts[0]; const position = parts[1]; placementList = position === "信息流" ? [1] : position === "搜索" ? [2] : null; } const requestBody = { startTime: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], endTime: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], [searchType]: searchValue, pageNum: 1, pageSize: 50 }; if (placementList) { requestBody.placementList = placementList; } const response = await fetch( "https://ad.xiaohongshu.com/api/leona/rtb/creativity/list", { headers, referrer: "https://ad.xiaohongshu.com/aurora/ad/manage/creativity", referrerPolicy: "strict-origin-when-cross-origin", body: JSON.stringify(requestBody), method: "POST", mode: "cors", credentials: "include" } ); const result = await response.json(); if (result.data.list.length > 0) { const creativeIds = result.data.list.map((item) => item.creativityId); message.info(`找到 ${creativeIds.length} 个创意ID`); const chunkedIds = chunkArray(creativeIds, 50); await toggleCreativePlan(chunkedIds, actionType); } else { message.warning(`未找到匹配的创意: ${searchValue}`); } } catch (error) { message.error(`处理 ${inputItem} 时出错: ${error.message}`); } } }; const handleSubmit = (e) => { e.preventDefault(); formRef.value?.validate(async (errors) => { if (!errors) { loading.value = true; showProgress.value = true; progress.value = 0; progressInfo.value = "开始处理..."; progressDetail.value = ""; try { const inputLines = formValue.inputContent.trim().split(/\r?\n/).map((line) => line.trim()).filter((line) => line !== ""); if (inputLines.length === 0) { message.error("请输入有效内容"); return; } if (formValue.searchType === "creativeId") { const invalidIds = inputLines.filter((line) => line.length < 11); if (invalidIds.length > 0) { message.error(`以下内容不符合创意ID格式: ${invalidIds.join(", ")}`); return; } const chunkedIds = chunkArray(inputLines, 50); await toggleCreativePlan(chunkedIds, formValue.actionType); } else { if (formValue.searchType === "noteId") { const invalidIds = inputLines.filter((line) => { const id = line.split(" ")[0]; return id.length <= 11; }); if (invalidIds.length > 0) { message.error(`以下内容不符合笔记ID格式: ${invalidIds.join(", ")}`); return; } } await toggleCreativeByNoteOrName(inputLines, formValue.actionType, formValue.searchType); } message.success("操作完成"); showModal.value = false; } catch (error) { message.error("操作失败: " + (error.message || "未知错误")); console.error("操作过程中出错:", error); } finally { loading.value = false; showProgress.value = false; } } else { message.error("请检查表单填写是否正确"); } }); }; return (_ctx, _cache) => { const _component_n_select = vue.resolveComponent("n-select"); const _component_n_form_item = vue.resolveComponent("n-form-item"); const _component_n_input = vue.resolveComponent("n-input"); const _component_n_text = vue.resolveComponent("n-text"); const _component_n_form = vue.resolveComponent("n-form"); const _component_n_button = vue.resolveComponent("n-button"); const _component_n_space = vue.resolveComponent("n-space"); const _component_n_modal = vue.resolveComponent("n-modal"); const _component_n_progress = vue.resolveComponent("n-progress"); return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [ vue.createVNode(_component_n_modal, { show: showModal.value, "onUpdate:show": _cache[3] || (_cache[3] = ($event) => showModal.value = $event), preset: "card", style: { "width": "600px" }, title: "创意开关控制", "mask-closable": false, "close-on-esc": false }, { footer: vue.withCtx(() => [ vue.createVNode(_component_n_space, { justify: "end" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { onClick: closeModal }, { default: vue.withCtx(() => _cache[6] || (_cache[6] = [ vue.createTextVNode("取消", -1) ])), _: 1, __: [6] }), vue.createVNode(_component_n_button, { type: "primary", onClick: handleSubmit, loading: loading.value }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(loading.value ? "处理中..." : "确认执行"), 1) ]), _: 1 }, 8, ["loading"]) ]), _: 1 }) ]), default: vue.withCtx(() => [ vue.createVNode(_component_n_form, { model: formValue, rules, ref_key: "formRef", ref: formRef }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_form_item, { label: "搜索方式", path: "searchType" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_select, { value: formValue.searchType, "onUpdate:value": _cache[0] || (_cache[0] = ($event) => formValue.searchType = $event), options: searchTypeOptions }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_form_item, { label: "操作类型", path: "actionType" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_select, { value: formValue.actionType, "onUpdate:value": _cache[1] || (_cache[1] = ($event) => formValue.actionType = $event), options: actionTypeOptions }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_form_item, { label: "输入内容", path: "inputContent" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: formValue.inputContent, "onUpdate:value": _cache[2] || (_cache[2] = ($event) => formValue.inputContent = $event), type: "textarea", placeholder: "请输入内容,多个内容请换行分隔", autosize: { minRows: 4, maxRows: 10 } }, null, 8, ["value"]), vue.createVNode(_component_n_text, { depth: "3", style: { "margin-top": "8px", "display": "block" } }, { default: vue.withCtx(() => _cache[5] || (_cache[5] = [ vue.createTextVNode(" 提示:使用创意ID时每行一个;使用笔记ID或文字匹配时,如需指定位置可在内容后加制表符(Tab)和位置(如:信息流、搜索) ", -1) ])), _: 1, __: [5] }) ]), _: 1 }) ]), _: 1 }, 8, ["model"]) ]), _: 1 }, 8, ["show"]), vue.createVNode(_component_n_modal, { show: showProgress.value, "onUpdate:show": _cache[4] || (_cache[4] = ($event) => showProgress.value = $event), preset: "card", style: { "width": "500px" }, title: "执行进度", "mask-closable": false, "close-on-esc": false }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_space, { vertical: "" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_text, null, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(progressInfo.value), 1) ]), _: 1 }), vue.createVNode(_component_n_progress, { type: "line", percentage: progress.value, "indicator-placement": "inside", processing: "" }, null, 8, ["percentage"]), vue.createVNode(_component_n_text, { depth: "3" }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(progressDetail.value), 1) ]), _: 1 }) ]), _: 1 }) ]), _: 1 }, 8, ["show"]) ], 64); }; } }; const setplan = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-8edd34a0"]]); const _hoisted_1$6 = { class: "createrplan-container" }; const _hoisted_2$1 = { style: { "font-size": "14px" } }; const _hoisted_3 = { style: { "font-size": "16px" } }; const _sfc_main$7 = { __name: "createrplan", setup(__props) { const message = naive.useMessage(); const currentVersion = vue.ref("old"); const isLoading = vue.ref({ autoOptimize: false, searchComponent: false, updateNames: false, addKeywords: false, addTracking: false }); const selectorConfig = { old: { autoOptimize: ".flexible.align-center", searchComponent: ".d-grid.d-radio-main-label", creativeNameInput: 'input[placeholder="请输入你的创意名称"]', item: ".item", commentInput: 'input[placeholder="请输入置顶评论文案"]', searchWordInput: 'input[placeholder="请输入搜索词"]', linkButton: ".link-text", addAction: ".add-action", linkInput: 'input[placeholder="请输入链接"]', saveButton: ".d-button-content .d-text" }, new: { autoOptimize: ".form-item-main button", searchComponent: ".search-component-new", creativeNameInput: 'input[placeholder="请输入创意名称"]', item: ".creativity-list-container", commentInput: 'input[placeholder="请输入置顶评论文案"]', searchWordInput: 'input[placeholder="请输入搜索词"]', linkButton: ".form-item-main button", addAction: ".add-action", linkInput: 'input[placeholder="请输入链接"]', saveButton: ".d-modal-footer button" } }; const getSelectors = () => selectorConfig[currentVersion.value]; const formData = vue.ref({ baseCreativeName: "", exposureLink: "", clickLink: "", noteMatchingInfo: "" }); vue.onMounted(() => { formData.value.baseCreativeName = localStorage.getItem("baseCreativeName") || ""; formData.value.exposureLink = localStorage.getItem("exposureLink") || ""; formData.value.clickLink = localStorage.getItem("clickLink") || ""; formData.value.noteMatchingInfo = localStorage.getItem("noteMatchingInfo") || ""; currentVersion.value = localStorage.getItem("currentVersion") || "old"; }); const switchVersion = () => { currentVersion.value = currentVersion.value === "old" ? "new" : "old"; localStorage.setItem("currentVersion", currentVersion.value); message.success( `已切换到${currentVersion.value === "old" ? "老版本" : "新版本"}` ); }; const saveToLocalStorage = (key, value) => { localStorage.setItem(key, value); }; const delay = (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; const waitForElement = async (selector, text = null) => { while (true) { const elements = Array.from(document.querySelectorAll(selector)); const el = elements.find((e) => !text || e.innerText.includes(text)); if (el) return el; await delay(100); } }; const waitForElements = async (selector, count) => { while (true) { const els = document.querySelectorAll(selector); if (els.length >= count) return els; await delay(100); } }; const parseNoteInfo = () => { const text = formData.value.noteMatchingInfo; return text.trim().split("\n").map((line) => line.trim().split(" ")); }; const setupAutoOptimize = async () => { isLoading.value.autoOptimize = true; try { const selectors = getSelectors(); document.querySelectorAll(selectors.autoOptimize).forEach((el) => { if (el.innerText === "关闭") { el.click(); } }); message.success(`已关闭自动优化 (${currentVersion.value}版本)`); } catch (error) { message.error("关闭自动优化失败: " + error.message); } finally { isLoading.value.autoOptimize = false; } }; const setupSearchComponent = async () => { isLoading.value.searchComponent = true; try { const selectors = getSelectors(); document.querySelectorAll(selectors.searchComponent).forEach((el) => { if (el.innerText === "搜索组件") { el.click(); } }); message.success(`已点击搜索组件 (${currentVersion.value}版本)`); } catch (error) { message.error("点击搜索组件失败: " + error.message); } finally { isLoading.value.searchComponent = false; } }; const updateCreativeNames = async () => { if (currentVersion.value === "new") { const selectors = getSelectors(); const baseName = formData.value.baseCreativeName; if (!baseName) { message.warning("请先输入基础创意名称"); return; } const xhsINFO = document.querySelectorAll( ".promotion-note-content-info span:nth-child(3)" ); console.log(xhsINFO); const inputg = document.querySelectorAll(selectors.creativeNameInput); console.log(inputg); for (let index = 0; index < inputg.length; index++) { const element = inputg[index]; element.value = baseName.replace("达人昵称", xhsINFO[index].innerText.split(" ")[0]); element.dispatchEvent(new Event("input")); } } else { isLoading.value.updateNames = true; try { const baseName = formData.value.baseCreativeName; const noteInfo = parseNoteInfo(); const selectors = getSelectors(); if (!baseName) { message.warning("请先输入基础创意名称"); return; } document.querySelectorAll(selectors.item).forEach((item) => { const tds = item.querySelectorAll("td"); if (tds.length >= 4) { const redbookId = tds[1].innerText; const nickname = tds[3].innerText; const scene = noteInfo.find((n) => n[1] === redbookId)?.[0]; if (scene) { const input = item.querySelector(selectors.creativeNameInput); if (input) { const newName = baseName.replace("达人昵称", nickname).replace("场景", scene); input.value = newName; input.dispatchEvent(new Event("input")); } } else { const input = item.querySelector(selectors.creativeNameInput); if (input) { const newName = baseName.replace("达人昵称", nickname); input.value = newName; input.dispatchEvent(new Event("input")); } } } }); message.success(`已完成创意名称修改 (${currentVersion.value}版本)`); } catch (error) { message.error("修改创意名称失败: " + error.message); } finally { isLoading.value.updateNames = false; } } }; const addSearchKeywords = async () => { isLoading.value.addKeywords = true; try { const noteInfo = parseNoteInfo(); const selectors = getSelectors(); document.querySelectorAll(selectors.item).forEach((item) => { const tds = item.querySelectorAll("td"); if (tds.length >= 2) { const redbookId = tds[1].innerText; const keyword = noteInfo.find((n) => n[1] === redbookId)?.[2]; if (keyword) { const inputs = [ item.querySelectorAll(selectors.commentInput)[1], item.querySelector(selectors.searchWordInput) ]; inputs.forEach((input, i) => { if (input) { input.value = i === 0 ? keyword : keyword.match(new RegExp("(?<=【).*?(?=】)", "g"))?.[0] || ""; input.dispatchEvent( new Event("input", { bubbles: true, cancelable: true, composed: true }) ); } }); } } }); message.success(`已完成搜索词添加 (${currentVersion.value}版本)`); } catch (error) { message.error("添加搜索词失败: " + error.message); } finally { isLoading.value.addKeywords = false; } }; const addTrackingLinks = async () => { isLoading.value.addTracking = true; try { const urls = [formData.value.exposureLink, formData.value.clickLink]; const selectors = getSelectors(); if (!urls[0] || !urls[1]) { message.warning("请先输入曝光链接和点击链接"); return; } const buttons = Array.from( document.querySelectorAll(selectors.linkButton) ).filter( (el) => el.innerText === "添加监测链接" || el.innerText === "去配置" ); for (const btn of buttons) { btn.click(); await waitForElements(selectors.addAction, 2); document.querySelectorAll(selectors.addAction).forEach((b) => b.click()); await delay(1e3); const inputs = await waitForElements(selectors.linkInput, 2); inputs.forEach((input, i) => { if (urls[i]) { input.value = urls[i]; input.dispatchEvent(new Event("input")); } }); await delay(1e3); const saveButton = await waitForElement(selectors.saveButton, "保存"); saveButton.click(); await delay(1e3); } message.success(`已完成监测链接添加 (${currentVersion.value}版本)`); } catch (error) { message.error("添加监测链接失败: " + error.message); } finally { isLoading.value.addTracking = false; } }; const clearAllData = () => { try { const keys = [ "baseCreativeName", "exposureLink", "clickLink", "noteMatchingInfo" ]; keys.forEach((key) => { localStorage.removeItem(key); formData.value[key] = ""; }); message.success("已清除所有数据"); } catch (error) { message.error("清除数据失败: " + error.message); } }; return (_ctx, _cache) => { const _component_n_tag = vue.resolveComponent("n-tag"); const _component_n_input = vue.resolveComponent("n-input"); const _component_n_form_item = vue.resolveComponent("n-form-item"); const _component_n_button = vue.resolveComponent("n-button"); const _component_n_grid_item = vue.resolveComponent("n-grid-item"); const _component_n_grid = vue.resolveComponent("n-grid"); const _component_n_space = vue.resolveComponent("n-space"); const _component_n_card = vue.resolveComponent("n-card"); return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, [ vue.createVNode(_component_n_card, { title: "小红书创意计划工具1.2", class: "main-card" }, { "header-extra": vue.withCtx(() => [ vue.createVNode(_component_n_tag, { type: currentVersion.value === "old" ? "warning" : "success", size: "large" }, { icon: vue.withCtx(() => [ vue.createElementVNode("span", _hoisted_2$1, vue.toDisplayString(currentVersion.value === "old" ? "🕰️" : "🚀"), 1) ]), default: vue.withCtx(() => [ vue.createTextVNode(" " + vue.toDisplayString(currentVersion.value === "old" ? "老版本" : "新版本"), 1) ]), _: 1 }, 8, ["type"]) ]), default: vue.withCtx(() => [ vue.createVNode(_component_n_space, { vertical: "" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_form_item, { label: "基础创意名称" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: formData.value.baseCreativeName, "onUpdate:value": [ _cache[0] || (_cache[0] = ($event) => formData.value.baseCreativeName = $event), _cache[1] || (_cache[1] = ($event) => saveToLocalStorage("baseCreativeName", $event)) ], placeholder: "请输入基础创意名称 【达人昵称】-信息流" }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_form_item, { label: "曝光链接" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: formData.value.exposureLink, "onUpdate:value": [ _cache[2] || (_cache[2] = ($event) => formData.value.exposureLink = $event), _cache[3] || (_cache[3] = ($event) => saveToLocalStorage("exposureLink", $event)) ], placeholder: "请输入曝光链接" }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_form_item, { label: "点击链接" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: formData.value.clickLink, "onUpdate:value": [ _cache[4] || (_cache[4] = ($event) => formData.value.clickLink = $event), _cache[5] || (_cache[5] = ($event) => saveToLocalStorage("clickLink", $event)) ], placeholder: "请输入点击链接" }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_form_item, { label: "笔记匹配信息" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: formData.value.noteMatchingInfo, "onUpdate:value": [ _cache[6] || (_cache[6] = ($event) => formData.value.noteMatchingInfo = $event), _cache[7] || (_cache[7] = ($event) => saveToLocalStorage("noteMatchingInfo", $event)) ], type: "textarea", placeholder: "直接从EXCEL中复制格式:\n小红书笔记id 达人昵称 ", autosize: { minRows: 4, maxRows: 6 } }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_grid, { cols: 3, "x-gap": 12, "y-gap": 12 }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "primary", block: "", onClick: setupAutoOptimize, loading: isLoading.value.autoOptimize }, { icon: vue.withCtx(() => _cache[8] || (_cache[8] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "⚙️", -1) ])), default: vue.withCtx(() => [ _cache[9] || (_cache[9] = vue.createTextVNode(" 关闭自动优化 ", -1)) ]), _: 1, __: [9] }, 8, ["loading"]) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "primary", block: "", onClick: setupSearchComponent, loading: isLoading.value.searchComponent }, { icon: vue.withCtx(() => _cache[10] || (_cache[10] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "🔍", -1) ])), default: vue.withCtx(() => [ _cache[11] || (_cache[11] = vue.createTextVNode(" 点击搜索组件 ", -1)) ]), _: 1, __: [11] }, 8, ["loading"]) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: currentVersion.value === "old" ? "success" : "warning", block: "", onClick: switchVersion }, { icon: vue.withCtx(() => [ vue.createElementVNode("span", _hoisted_3, vue.toDisplayString(currentVersion.value === "old" ? "🚀" : "🕰️"), 1) ]), default: vue.withCtx(() => [ vue.createTextVNode(" 切换到" + vue.toDisplayString(currentVersion.value === "old" ? "新版本" : "老版本"), 1) ]), _: 1 }, 8, ["type"]) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "info", block: "", onClick: updateCreativeNames, loading: isLoading.value.updateNames }, { icon: vue.withCtx(() => _cache[12] || (_cache[12] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "✏️", -1) ])), default: vue.withCtx(() => [ _cache[13] || (_cache[13] = vue.createTextVNode(" 修改创意名称 ", -1)) ]), _: 1, __: [13] }, 8, ["loading"]) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "info", block: "", onClick: addSearchKeywords, loading: isLoading.value.addKeywords }, { icon: vue.withCtx(() => _cache[14] || (_cache[14] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "🏷️", -1) ])), default: vue.withCtx(() => [ _cache[15] || (_cache[15] = vue.createTextVNode(" 添加搜索词 ", -1)) ]), _: 1, __: [15] }, 8, ["loading"]) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "warning", block: "", onClick: addTrackingLinks, loading: isLoading.value.addTracking }, { icon: vue.withCtx(() => _cache[16] || (_cache[16] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "🔗", -1) ])), default: vue.withCtx(() => [ _cache[17] || (_cache[17] = vue.createTextVNode(" 添加监测链接 ", -1)) ]), _: 1, __: [17] }, 8, ["loading"]) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "error", block: "", onClick: clearAllData }, { icon: vue.withCtx(() => _cache[18] || (_cache[18] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "🗑️", -1) ])), default: vue.withCtx(() => [ _cache[19] || (_cache[19] = vue.createTextVNode(" 清除所有数据 ", -1)) ]), _: 1, __: [19] }) ]), _: 1 }) ]), _: 1 }) ]), _: 1 }) ]), _: 1 }) ]); }; } }; const createrplan = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-5dbab58c"]]); const _hoisted_1$5 = { class: "button-container" }; const _hoisted_2 = { class: "modal-content" }; const _sfc_main$6 = { __name: "XHS", setup(__props) { const linkChecker = new LinkChecker(); const message = naive.useMessage(); const checkingLinks = vue.ref(false); const showDataModal = vue.ref(false); const tableData = vue.ref([]); const linkStats = vue.reactive({ totalCreativity: 0, clickUrlCounts: [], expoUrlCounts: [] }); const showRenameModal = vue.ref(false); const showBatchPriceModal = vue.ref(false); const showSetPlanModal = vue.ref(false); const createplanRef = vue.ref(false); const tableColumns = [ { title: "创建时间", key: "creativityCreateTime", width: 150 }, { title: "创意名", key: "creativityName", resizable: true }, { title: "创意ID", key: "creativityId", width: 120 }, { title: "点击链接", key: "clickUrls", render(row) { return row.clickUrls ? row.clickUrls.map((url) => linkChecker.extractUrlParam(url)).join("\n") : ""; } }, { title: "曝光链接", key: "expoUrls", render(row) { return row.expoUrls ? row.expoUrls.map((url) => linkChecker.extractUrlParam(url)).join("\n") : ""; } } ]; function downloadData() { linkChecker.downloadCSV(); } const pagination = vue.reactive({ page: 1, pageSize: 10, showSizePicker: true, pageSizes: [10, 20, 50], prefix({ itemCount }) { return `总共有 ${itemCount} 条数据`; }, onChange: (page) => { pagination.page = page; console.log(`切换到第 ${page} 页`); }, onUpdatePageSize: (pageSize) => { pagination.pageSize = pageSize; pagination.page = 1; console.log(`每页显示 ${pageSize} 条数据`); } }); const checkAndShowLinks = async () => { checkingLinks.value = true; try { const result = await linkChecker.checkLinks(); if (result.success) { console.log("检查成功", result.data); const state = linkChecker.getState(); tableData.value = state.tableData; linkStats.totalCreativity = state.stats.totalCreativity; linkStats.clickUrlCounts = state.stats.clickUrlCounts; linkStats.expoUrlCounts = state.stats.expoUrlCounts; showDataModal.value = true; message.success("成功", { duration: 3e3, closable: true }); } else { console.error("检查失败", result.error); message.info("失败", { duration: 3e3, closable: true }); } } catch { message.error("失败", { duration: 3e3, closable: true }); } finally { checkingLinks.value = false; } }; const modifyCreativeNames = () => { if (showRenameModal.value) { showRenameModal.value = false; console.log("隐藏修改创模态窗口"); } else { showRenameModal.value = true; console.log("修改创模态窗口"); } console.log("修改创意名称"); }; const batchPriceAdjustment = () => { console.log("批量调价"); showBatchPriceModal.value = true; }; const enableCreatives = () => { console.log("开启创意"); showSetPlanModal.value = true; }; return (_ctx, _cache) => { const _component_n_icon = vue.resolveComponent("n-icon"); const _component_n_button = vue.resolveComponent("n-button"); const _component_n_tooltip = vue.resolveComponent("n-tooltip"); const _component_n_space = vue.resolveComponent("n-space"); const _component_n_statistic = vue.resolveComponent("n-statistic"); const _component_n_card = vue.resolveComponent("n-card"); const _component_n_grid_item = vue.resolveComponent("n-grid-item"); const _component_n_grid = vue.resolveComponent("n-grid"); const _component_n_ellipsis = vue.resolveComponent("n-ellipsis"); const _component_n_list_item = vue.resolveComponent("n-list-item"); const _component_n_list = vue.resolveComponent("n-list"); const _component_n_scrollbar = vue.resolveComponent("n-scrollbar"); const _component_n_data_table = vue.resolveComponent("n-data-table"); const _component_n_modal = vue.resolveComponent("n-modal"); return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [ vue.createElementVNode("div", _hoisted_1$5, [ vue.createVNode(_component_n_space, { justify: "space-between", wrap: "" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "primary", size: "large", onClick: checkAndShowLinks, loading: checkingLinks.value, style: { "flex": "1", "min-width": "150px", "margin": "4px" } }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[6] || (_cache[6] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [6] }) ]), default: vue.withCtx(() => [ vue.createTextVNode(" " + vue.toDisplayString(checkingLinks.value ? "检查中..." : "检查链接"), 1) ]), _: 1 }, 8, ["loading"]), vue.createVNode(_component_n_button, { type: "info", size: "large", onClick: modifyCreativeNames, style: { "flex": "1", "min-width": "150px", "margin": "4px" } }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[7] || (_cache[7] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [7] }) ]), default: vue.withCtx(() => [ _cache[8] || (_cache[8] = vue.createTextVNode(" 修改名称 ", -1)) ]), _: 1, __: [8] }), vue.createVNode(_component_n_tooltip, { trigger: "hover" }, { trigger: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "warning", size: "large", onClick: batchPriceAdjustment, style: { "flex": "1", "min-width": "150px", "margin": "4px" }, disabled: true }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[9] || (_cache[9] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [9] }) ]), default: vue.withCtx(() => [ _cache[10] || (_cache[10] = vue.createTextVNode(" 批量调价 ", -1)) ]), _: 1, __: [10] }) ]), default: vue.withCtx(() => [ _cache[11] || (_cache[11] = vue.createElementVNode("span", null, "当前调价功能存在问题,暂时无法使用", -1)) ]), _: 1, __: [11] }), vue.createVNode(_component_n_button, { type: "success", size: "large", onClick: enableCreatives, style: { "flex": "1", "min-width": "150px", "margin": "4px" } }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[12] || (_cache[12] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [12] }) ]), default: vue.withCtx(() => [ _cache[13] || (_cache[13] = vue.createTextVNode(" 关闭创意 ", -1)) ]), _: 1, __: [13] }), vue.createVNode(_component_n_button, { type: "success", size: "large", onClick: _cache[0] || (_cache[0] = ($event) => createplanRef.value = true), style: { "flex": "1", "min-width": "150px", "margin": "4px" } }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[14] || (_cache[14] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [14] }) ]), default: vue.withCtx(() => [ _cache[15] || (_cache[15] = vue.createTextVNode(" 半自动搭建创意 ", -1)) ]), _: 1, __: [15] }) ]), _: 1 }), vue.createVNode(_component_n_modal, { show: showDataModal.value, "onUpdate:show": _cache[1] || (_cache[1] = ($event) => showDataModal.value = $event), preset: "card", style: { "width": "90vw" }, title: "链接检查结果", "mask-closable": false, "close-on-esc": false }, { "header-extra": vue.withCtx(() => [ vue.createVNode(_component_n_button, { strong: "", secondary: "", onClick: downloadData }, { default: vue.withCtx(() => _cache[16] || (_cache[16] = [ vue.createTextVNode(" 下载数据 ", -1) ])), _: 1, __: [16] }) ]), default: vue.withCtx(() => [ vue.createElementVNode("div", _hoisted_2, [ linkStats.totalCreativity > 0 ? (vue.openBlock(), vue.createBlock(_component_n_grid, { key: 0, cols: 3, responsive: "screen", "x-gap": 12, "y-gap": 12 }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_card, { title: "总创意数" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_statistic, { value: linkStats.totalCreativity }, null, 8, ["value"]) ]), _: 1 }) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_card, { title: "点击链接种类" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_statistic, { value: linkStats.clickUrlCounts.length }, null, 8, ["value"]) ]), _: 1 }) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_card, { title: "曝光链接种类" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_statistic, { value: linkStats.expoUrlCounts.length }, null, 8, ["value"]) ]), _: 1 }) ]), _: 1 }) ]), _: 1 })) : vue.createCommentVNode("", true), linkStats.clickUrlCounts.length > 0 ? (vue.openBlock(), vue.createBlock(_component_n_card, { key: 1, title: "点击链接统计", style: { "margin-top": "16px" }, class: "auto-height-card" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_scrollbar, { style: { "max-height": "150px" } }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_list, null, { default: vue.withCtx(() => [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(linkStats.clickUrlCounts, (item) => { return vue.openBlock(), vue.createBlock(_component_n_list_item, { key: item.url }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_ellipsis, { style: { "max-width": "100%" }, tooltip: true }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(item.displayUrl) + " :" + vue.toDisplayString(item.count) + " 条 ", 1) ]), _: 2 }, 1024) ]), _: 2 }, 1024); }), 128)) ]), _: 1 }) ]), _: 1 }) ]), _: 1 })) : vue.createCommentVNode("", true), linkStats.expoUrlCounts.length > 0 ? (vue.openBlock(), vue.createBlock(_component_n_card, { key: 2, title: "曝光链接统计", style: { "margin-top": "16px" } }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_scrollbar, { style: { "max-height": "150px" } }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_list, null, { default: vue.withCtx(() => [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(linkStats.expoUrlCounts, (item) => { return vue.openBlock(), vue.createBlock(_component_n_list_item, { key: item.url }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_ellipsis, { style: { "max-width": "100%" }, tooltip: true }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(item.displayUrl) + " :" + vue.toDisplayString(item.count) + " 条 ", 1) ]), _: 2 }, 1024) ]), _: 2 }, 1024); }), 128)) ]), _: 1 }) ]), _: 1 }) ]), _: 1 })) : vue.createCommentVNode("", true), vue.createVNode(_component_n_card, { title: "详细数据", style: { "margin-top": "16px", "flex": "1" } }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_data_table, { columns: tableColumns, data: tableData.value, pagination, striped: "", bordered: true }, null, 8, ["data", "pagination"]) ]), _: 1 }) ]) ]), _: 1 }, 8, ["show"]), vue.createVNode(_component_n_modal, { show: createplanRef.value, "onUpdate:show": _cache[2] || (_cache[2] = ($event) => createplanRef.value = $event), preset: "card", style: { "width": "800px", "max-width": "90vw" }, title: "红书半自动搭建计划", bordered: false, "mask-closable": true, "close-on-esc": true }, { default: vue.withCtx(() => [ vue.createVNode(createrplan) ]), _: 1 }, 8, ["show"]) ]), vue.createVNode(rename, { show: showRenameModal.value, "onUpdate:show": _cache[3] || (_cache[3] = ($event) => showRenameModal.value = $event) }, null, 8, ["show"]), vue.createVNode(BatchPrice, { show: showBatchPriceModal.value, "onUpdate:show": _cache[4] || (_cache[4] = ($event) => showBatchPriceModal.value = $event) }, null, 8, ["show"]), vue.createVNode(setplan, { show: showSetPlanModal.value, "onUpdate:show": _cache[5] || (_cache[5] = ($event) => showSetPlanModal.value = $event) }, null, 8, ["show"]) ], 64); }; } }; const XHS = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-aaaae17f"]]); const _hoisted_1$4 = { class: "default-component" }; const _sfc_main$5 = { __name: "DefaultComponent", setup(__props) { return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$4, [ vue.createVNode(vue.unref(naive.NEmpty), { description: "暂无适配" }, { icon: vue.withCtx(() => [ vue.createVNode(vue.unref(naive.NIcon), { size: "48" }, { default: vue.withCtx(() => _cache[0] || (_cache[0] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [0] }) ]), _: 1 }) ]); }; } }; const DefaultComponent = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-ff0a68db"]]); class RequestListener { constructor() { this.isActive = false; this.originalXHR = null; this.originalFetch = null; this.callbacks = []; } // 解码函数 decodeRequestBody(body) { try { if (typeof body === "string") { if (body.trim().startsWith("{") || body.trim().startsWith("[")) { const parsed = JSON.parse(body); return parsed; } else { return body; } } else if (typeof body === "object") { return body; } else { return body; } } catch (e) { return body; } } // 启动监听器 start() { if (this.isActive) return false; this.originalXHR = window.XMLHttpRequest; this.originalFetch = window.fetch; const self = this; window.XMLHttpRequest = function() { const xhr = new self.originalXHR(); const originalOpen = xhr.open; const originalSend = xhr.send; let requestUrl = ""; let method = ""; xhr.open = function(xhrMethod, url) { requestUrl = url; method = xhrMethod; return originalOpen.apply(this, arguments); }; xhr.send = function(body) { if (requestUrl.includes("queryJobPs")) { const decodedBody = self.decodeRequestBody(body); self.callbacks.forEach((callback) => { callback({ type: "xhr", url: requestUrl, method, requestBody: body, decodedBody }); }); } return originalSend.apply(this, arguments); }; return xhr; }; window.fetch = function(input, init) { let url = ""; if (typeof input === "string") { url = input; } else if (input instanceof Request) { url = input.url; } else { url = String(input); } if (url.includes("queryJobPs")) { let body = null; if (init && init.body) { body = init.body; } const decodedBody = self.decodeRequestBody(body); self.callbacks.forEach((callback) => { callback({ type: "fetch", url, init, requestBody: body, decodedBody }); }); } return self.originalFetch.apply(this, arguments); }; this.isActive = true; return true; } // 停止监听器 stop() { if (!this.isActive) return false; if (this.originalXHR) { window.XMLHttpRequest = this.originalXHR; } if (this.originalFetch) { window.fetch = this.originalFetch; } this.isActive = false; return true; } // 添加回调函数 addCallback(callback) { if (typeof callback === "function") { this.callbacks.push(callback); } } // 移除回调函数 removeCallback(callback) { const index = this.callbacks.indexOf(callback); if (index > -1) { this.callbacks.splice(index, 1); } } // 获取监听器状态 getStatus() { return this.isActive; } } const requestListener = new RequestListener(); const _hoisted_1$3 = { class: "jihua-container" }; const _sfc_main$4 = { __name: "chuangyi", setup(__props) { const message = naive.useMessage(); const inputData = vue.ref(""); const loading = vue.ref(false); const isEnable = vue.ref(false); function closeInfoStream(mediaIdList) { return fetch("https://galaxy.alibaba-inc.com/creativePlan/automatedSetUp", { "headers": { "accept": "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "appname": "adcontent-op", "bx-v": "2.5.31", "content-type": "application/json", "priority": "u=1, i", "sec-ch-ua": '"Not)A;Brand";v="8", "Chromium";v="138", "Microsoft Edge";v="138"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"macOS"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin" }, "referrer": "https://galaxy.alibaba-inc.com/", "body": JSON.stringify({ "mediaCode": 0, "opType": 2, "taskOpType": 7, "taskType": 3, "name": !isEnable ? "创意开启" : "创意关闭", "campaignSettings": '{"startTime":null}', "unitSettings": "{}", "creativeSettings": !isEnable ? '{"status":1}' : '{"status":2}', "ext": '{"marketingTarget":4,"placement":1,"optimizeTarget":0,"type":"creative"}', "mediaIdList": mediaIdList }), "method": "POST", "mode": "cors", "credentials": "include" }); } function closeSearch(mediaIdList) { return fetch("https://galaxy.alibaba-inc.com/creativePlan/automatedSetUp", { "headers": { "accept": "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "appname": "adcontent-op", "bx-v": "2.5.31", "content-type": "application/json", "priority": "u=1, i", "sec-ch-ua": '"Not)A;Brand";v="8", "Chromium";v="138", "Microsoft Edge";v="138"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"macOS"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin" }, "referrer": "https://galaxy.alibaba-inc.com/", "body": JSON.stringify({ "mediaCode": 0, "opType": 2, "taskOpType": 7, "taskType": 3, "name": !isEnable ? "创意开启" : "创意关闭", "campaignSettings": '{"startTime":null}', "unitSettings": "{}", "creativeSettings": !isEnable ? '{"status":1}' : '{"status":2}', "ext": '{"marketingTarget":4,"placement":2,"optimizeTarget":0,"type":"creative"}', "mediaIdList": mediaIdList }), "method": "POST", "mode": "cors", "credentials": "include" }); } function handleSubmit() { if (!inputData.value.trim()) { message.warning("请输入需要处理的数据"); return; } loading.value = true; try { const rows = inputData.value.trim().split("\n").map((row) => row.trim().split(" ")); const infoStreamMediaIds = []; const searchMediaIds = []; rows.forEach((row) => { if (row[0] === "信息流") { infoStreamMediaIds.push(row[1]); } else if (row[0] === "搜索") { searchMediaIds.push(row[1]); } }); const promises = []; if (infoStreamMediaIds.length > 0) { promises.push(closeInfoStream(infoStreamMediaIds)); } if (searchMediaIds.length > 0) { promises.push(closeSearch(searchMediaIds)); } Promise.all(promises).then(() => { message.success("操作已提交成功"); loading.value = false; }).catch((error) => { console.error("操作失败:", error); message.error("操作执行失败"); loading.value = false; }); } catch (error) { console.error("处理数据时出错:", error); message.error("数据处理失败"); loading.value = false; } } return (_ctx, _cache) => { const _component_n_input = vue.resolveComponent("n-input"); const _component_n_checkbox = vue.resolveComponent("n-checkbox"); const _component_n_button = vue.resolveComponent("n-button"); const _component_n_space = vue.resolveComponent("n-space"); return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [ vue.createVNode(_component_n_space, { vertical: "" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: inputData.value, "onUpdate:value": _cache[0] || (_cache[0] = ($event) => inputData.value = $event), type: "textarea", placeholder: "请输入数据\n\n示例:\n搜索 2035614598\n信息流 2033338178\n搜索 2035670707", autosize: { minRows: 10, maxRows: 15 }, clearable: "" }, null, 8, ["value"]), vue.createVNode(_component_n_checkbox, { checked: isEnable.value, "onUpdate:checked": _cache[1] || (_cache[1] = ($event) => isEnable.value = $event) }, { default: vue.withCtx(() => _cache[2] || (_cache[2] = [ vue.createTextVNode(" 启用创意 (取消勾选则关闭创意) ", -1) ])), _: 1, __: [2] }, 8, ["checked"]), vue.createVNode(_component_n_button, { type: "primary", onClick: handleSubmit, loading: loading.value, disabled: !inputData.value.trim() }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(loading.value ? "处理中..." : "提交执行"), 1) ]), _: 1 }, 8, ["loading", "disabled"]) ]), _: 1 }) ]); }; } }; const chuangyi = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-f7d071d3"]]); const _hoisted_1$2 = { class: "plan-container" }; const _sfc_main$3 = { __name: "jihua", setup(__props) { const message = naive.useMessage(); const mode = vue.ref("close"); const budget = vue.ref(null); const inputData = vue.ref(""); const loading = vue.ref(false); function buildPayload(planType, planIds, options) { const placementMap = { 信息流: 1, 搜索: 2 }; const placement = placementMap[planType]; if (placement === void 0) { throw new Error(`未知的计划类型: "${planType}"`); } let campaignSettingsObj = {}; let taskName = ""; if (options.mode === "close") { campaignSettingsObj = { status: 2 }; taskName = "关闭"; } else if (options.mode === "adjust") { if (typeof options.budget !== "number" || options.budget <= 0) { throw new Error("预算金额无效。"); } campaignSettingsObj = { campaignDayBudget: options.budget, startTime: "2025-08-01" }; taskName = `调整预算至${options.budget}`; } const campaignSettings = JSON.stringify(campaignSettingsObj); const ext = JSON.stringify({ marketingTarget: 4, placement, optimizeTarget: 0, type: "plan" }); return { mediaCode: 0, opType: 2, taskOpType: options.mode === "close" ? 4 : 3, taskType: 1, name: taskName, campaignSettings, unitSettings: "{}", creativeSettings: "{}", ext, mediaIdList: planIds.map((id) => String(id)) // 确保所有ID是字符串 }; } async function sendBulkRequest(planType, planIds, options) { const url = "https://galaxy.alibaba-inc.com/creativePlan/automatedSetUp"; const actionText = options.mode === "close" ? "关闭" : `调价至 ${options.budget}`; console.log( `> 正在批量 [${actionText}] [${planType}] 类型的 ${planIds.length} 个计划...` ); console.log(" ID 列表:", planIds); try { const payload = buildPayload(planType, planIds, options); const response = await fetch(url, { method: "POST", headers: { accept: "application/json, text/plain, */*", "content-type": "application/json", appname: "adcontent-op" }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`HTTP 错误! 状态码: ${response.status}`); } const result = await response.json(); if (result.success || String(result.code) === "200") { message.success(`[${planType}] 类型的计划已提交 [${actionText}] 操作`); console.log( `✅ [成功] [${planType}] 类型的计划已提交 [${actionText}] 操作。响应:`, result.message || "OK" ); } else { message.error(`[${planType}] 类型的计划操作失败`); console.error( `❌ [失败] [${planType}] 类型的计划操作失败。业务响应:`, result.message || result ); } } catch (error) { message.error(`[${planType}] 类型的计划请求异常`); console.error(`❌ [失败] [${planType}] 类型的计划请求异常:`, error); } } function delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } const canSubmit = vue.computed(() => { if (!inputData.value.trim()) return false; if (mode.value === "adjust" && !budget.value) return false; return true; }); async function handleSubmit() { if (!inputData.value.trim()) { message.warning("请输入需要处理的数据"); return; } if (mode.value === "adjust" && !budget.value) { message.warning("请输入日预算金额"); return; } loading.value = true; try { const options = { mode: mode.value, budget: budget.value }; const groupedTasks = { 信息流: [], 搜索: [] }; const lines = inputData.value.trim().split("\n"); lines.forEach((line) => { const parts = line.trim().split(/\s+/); if (parts.length >= 2 && parts[1]) { const type = parts[0]; const id = parts[1]; if (groupedTasks[type]) { groupedTasks[type].push(id); } else { console.warn(`! 跳过未知类型 "${type}" 的行: ${line}`); } } }); const infoStreamIds = groupedTasks["信息流"]; const searchIds = groupedTasks["搜索"]; if (infoStreamIds.length === 0 && searchIds.length === 0) { message.error("未能解析出任何有效的任务,请检查数据格式"); loading.value = false; return; } let requestSent = false; if (infoStreamIds.length > 0) { await sendBulkRequest("信息流", infoStreamIds, options); requestSent = true; } if (searchIds.length > 0) { if (requestSent) { await delay(1e3); } await sendBulkRequest("搜索", searchIds, options); } message.success("全部批量任务处理完毕!"); loading.value = false; } catch (error) { console.error("处理数据时出错:", error); message.error("数据处理失败"); loading.value = false; } } return (_ctx, _cache) => { const _component_n_radio = vue.resolveComponent("n-radio"); const _component_n_space = vue.resolveComponent("n-space"); const _component_n_radio_group = vue.resolveComponent("n-radio-group"); const _component_n_input_number = vue.resolveComponent("n-input-number"); const _component_n_input = vue.resolveComponent("n-input"); const _component_n_button = vue.resolveComponent("n-button"); return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [ vue.createVNode(_component_n_space, { vertical: "" }, { default: vue.withCtx(() => [ _cache[6] || (_cache[6] = vue.createElementVNode("div", { class: "description" }, [ vue.createElementVNode("p", null, "请选择操作模式并输入需要处理的计划数据"), vue.createElementVNode("p", null, "数据格式:平台 + Tab + 计划ID"), vue.createElementVNode("p", null, "例如:"), vue.createElementVNode("pre", null, "搜索 2035614598\n信息流 2033338178\n搜索 2035670707") ], -1)), vue.createVNode(_component_n_radio_group, { value: mode.value, "onUpdate:value": _cache[0] || (_cache[0] = ($event) => mode.value = $event), name: "mode" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_space, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_radio, { value: "close" }, { default: vue.withCtx(() => _cache[3] || (_cache[3] = [ vue.createTextVNode(" 批量关闭计划 ", -1) ])), _: 1, __: [3] }), vue.createVNode(_component_n_radio, { value: "adjust" }, { default: vue.withCtx(() => _cache[4] || (_cache[4] = [ vue.createTextVNode(" 批量调整日预算 ", -1) ])), _: 1, __: [4] }) ]), _: 1 }) ]), _: 1 }, 8, ["value"]), mode.value === "adjust" ? (vue.openBlock(), vue.createBlock(_component_n_input_number, { key: 0, value: budget.value, "onUpdate:value": _cache[1] || (_cache[1] = ($event) => budget.value = $event), placeholder: "请输入新的日预算金额", min: 1, clearable: "" }, { prefix: vue.withCtx(() => _cache[5] || (_cache[5] = [ vue.createTextVNode(" ¥ ", -1) ])), _: 1 }, 8, ["value"])) : vue.createCommentVNode("", true), vue.createVNode(_component_n_input, { value: inputData.value, "onUpdate:value": _cache[2] || (_cache[2] = ($event) => inputData.value = $event), type: "textarea", placeholder: "请输入数据\n\n示例:\n搜索 2035614598\n信息流 2033338178\n搜索 2035670707", autosize: { minRows: 10, maxRows: 15 }, clearable: "" }, null, 8, ["value"]), vue.createVNode(_component_n_button, { type: "primary", onClick: handleSubmit, loading: loading.value, disabled: !canSubmit.value }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(loading.value ? "处理中..." : "提交执行"), 1) ]), _: 1 }, 8, ["loading", "disabled"]) ]), _: 1, __: [6] }) ]); }; } }; const jihua = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-f977d1aa"]]); const _hoisted_1$1 = { class: "button-container" }; const _sfc_main$2 = { __name: "app", setup(__props) { const showchuangyiModal = vue.ref(false); const showjihuaModal = vue.ref(false); const isListening = vue.ref(false); const message = naive.useMessage(); const listenerCallback = (data) => { console.log("捕获到queryJobPs请求:", data); message.info(`捕获到${data.type}类型的queryJobPs请求`); }; const toggleListener = () => { if (isListening.value) { requestListener.stop(); requestListener.removeCallback(listenerCallback); isListening.value = false; message.success("已停止监听queryJobPs请求"); } else { const started = requestListener.start(); if (started) { requestListener.addCallback(listenerCallback); isListening.value = true; message.success("已开始监听queryJobPs请求"); } else { message.warning("监听器已在运行中"); } } }; vue.onUnmounted(() => { if (isListening.value) { requestListener.stop(); requestListener.removeCallback(listenerCallback); } }); return (_ctx, _cache) => { const _component_n_icon = vue.resolveComponent("n-icon"); const _component_n_button = vue.resolveComponent("n-button"); const _component_n_space = vue.resolveComponent("n-space"); const _component_n_alert = vue.resolveComponent("n-alert"); const _component_n_modal = vue.resolveComponent("n-modal"); return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [ vue.createVNode(_component_n_space, { justify: "space-between", wrap: "" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "primary", size: "large", style: { "flex": "1", "min-width": "150px", "margin": "4px" }, onClick: _cache[0] || (_cache[0] = ($event) => showchuangyiModal.value = true) }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[4] || (_cache[4] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [4] }) ]), default: vue.withCtx(() => [ _cache[5] || (_cache[5] = vue.createTextVNode(" 创意关闭/开启 ", -1)) ]), _: 1, __: [5] }), vue.createVNode(_component_n_button, { type: "info", size: "large", style: { "flex": "1", "min-width": "150px", "margin": "4px" }, onClick: _cache[1] || (_cache[1] = ($event) => showjihuaModal.value = true) }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[6] || (_cache[6] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [6] }) ]), default: vue.withCtx(() => [ _cache[7] || (_cache[7] = vue.createTextVNode(" 计划关闭/调价 ", -1)) ]), _: 1, __: [7] }), vue.createVNode(_component_n_button, { type: isListening.value ? "error" : "warning", size: "large", style: { "flex": "1", "min-width": "150px", "margin": "4px" }, onClick: toggleListener }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(isListening.value ? "⏹️" : "▶️"), 1) ]), _: 1 }) ]), default: vue.withCtx(() => [ vue.createTextVNode(" " + vue.toDisplayString(isListening.value ? "停止监听" : "开始监听"), 1) ]), _: 1 }, 8, ["type"]), vue.createVNode(_component_n_button, { type: "success", size: "large", style: { "flex": "1", "min-width": "150px", "margin": "4px" } }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[8] || (_cache[8] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [8] }) ]), default: vue.withCtx(() => [ _cache[9] || (_cache[9] = vue.createTextVNode(" 功能按钮4 ", -1)) ]), _: 1, __: [9] }) ]), _: 1 }), isListening.value ? (vue.openBlock(), vue.createBlock(_component_n_alert, { key: 0, type: "info", style: { "margin-top": "20px" }, closable: "" }, { icon: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[10] || (_cache[10] = [ vue.createTextVNode("🔊", -1) ])), _: 1, __: [10] }) ]), default: vue.withCtx(() => [ _cache[11] || (_cache[11] = vue.createTextVNode(" 正在监听中...捕获到的queryJobPs请求将显示在浏览器控制台 ", -1)) ]), _: 1, __: [11] })) : vue.createCommentVNode("", true), vue.createVNode(_component_n_modal, { show: showchuangyiModal.value, "onUpdate:show": _cache[2] || (_cache[2] = ($event) => showchuangyiModal.value = $event), preset: "card", style: { "width": "800px", "max-width": "90vw" }, title: "批量关闭创意", bordered: false, "mask-closable": true, "close-on-esc": true }, { default: vue.withCtx(() => [ vue.createVNode(chuangyi) ]), _: 1 }, 8, ["show"]), vue.createVNode(_component_n_modal, { show: showjihuaModal.value, "onUpdate:show": _cache[3] || (_cache[3] = ($event) => showjihuaModal.value = $event), preset: "card", style: { "width": "800px", "max-width": "90vw" }, title: "计划批量关闭/调价操作", bordered: false, "mask-closable": true, "close-on-esc": true }, { default: vue.withCtx(() => [ vue.createVNode(jihua) ]), _: 1 }, 8, ["show"]) ]); }; } }; const zt = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-c6e92986"]]); const _hoisted_1 = { class: "kuaishou-container" }; const _sfc_main$1 = { __name: "kuaishou", setup(__props) { const message = naive.useMessage(); const formData = vue.ref({ batchData: "" }); const emailConfig = vue.ref({ apiKey: "", fromEmail: "", toEmails: "" }); const isProcessing = vue.ref(false); const isSendingEmail = vue.ref(false); const logs = vue.ref([]); const parsedData = vue.ref([]); const selectors = { title: [ 'input[placeholder="请输入广告计划名称"]', "#ad_from_unitName_unitName input.ant-input", 'input[placeholder="请输入创意名称"]' ], directLink: [ 'input[placeholder="填写后使用直达链接,不填则会使用落地页"]' ], h5Link: [ 'input[placeholder="请填写https://开头的链接;如投放原生广告,配置落地页应具备调起APP能力"]' ], exposure: [ "#ad_from_monitorLinks_impressionUrl input", "#ad_from_monitorLinks_clickUrl input" ], click: [ "#ad_from_monitorLinks_actionbarClickUrl input" ], other: [ 'input[placeholder="需遵守描述语规范,建议突出卖点和热点,有助于提升点击率,可在右侧预览展示效果"]' ] }; vue.onMounted(() => { loadFromLocalStorage(); addLog("快手广告填表工具已启动"); }); const loadFromLocalStorage = () => { formData.value.batchData = localStorage.getItem("ks_batchData") || ""; emailConfig.value.apiKey = localStorage.getItem("ks_apiKey") || ""; emailConfig.value.fromEmail = localStorage.getItem("ks_fromEmail") || ""; emailConfig.value.toEmails = localStorage.getItem("ks_toEmails") || ""; }; const saveToLocalStorage = (key, value) => { localStorage.setItem(`ks_${key}`, value); }; const addLog = (message2) => { const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString(); logs.value.unshift(`[${timestamp}] ${message2}`); if (logs.value.length > 50) { logs.value = logs.value.slice(0, 50); } }; const parseBatchData = () => { const lines = formData.value.batchData.trim().split("\n"); return lines.map((line, index) => { const parts = line.trim().split(" "); if (parts.length >= 3) { return { index: index + 1, title: parts[0] || "", h5Link: parts[1] || "", directLink: parts[2] || "", isIOS: (parts[0] || "").includes("IOS") || (parts[0] || "").includes("iOS") }; } return null; }).filter(Boolean); }; const previewData = () => { parsedData.value = parseBatchData(); if (parsedData.value.length === 0) { message.warning("请先输入有效的批量数据"); return; } addLog(`解析完成,共 ${parsedData.value.length} 条数据`); message.success(`已解析 ${parsedData.value.length} 条数据`); }; const setInputValue = (selectorArray, value) => { let successCount = 0; selectorArray.forEach((selector) => { try { const element = document.querySelector(selector); if (element) { element.value = value; const changeEvent = new Event("change", { bubbles: true }); element.dispatchEvent(changeEvent); const inputEvent = new Event("input", { bubbles: true }); element.dispatchEvent(inputEvent); const reactProp = Object.keys(element).find((p) => p.startsWith("__reactEventHandlers")); if (reactProp && element[reactProp] && element[reactProp].onChange) { element[reactProp].onChange(changeEvent); } successCount++; } } catch (error) { console.warn(`设置选择器 ${selector} 失败:`, error); } }); return successCount; }; const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const fillFormData = async () => { if (!formData.value.batchData.trim()) { message.warning("请先输入批量数据"); return; } isProcessing.value = true; try { const dataList = parseBatchData(); if (dataList.length === 0) { message.warning("没有有效的数据可以处理"); return; } addLog(`开始批量填充,共 ${dataList.length} 条数据`); const firstData = dataList[0]; const titleCount = setInputValue(selectors.title, firstData.title); addLog(`填充标题: ${firstData.title} (成功 ${titleCount} 个字段)`); await delay(300); const directCount = setInputValue(selectors.directLink, firstData.directLink); addLog(`填充直达链接: ${firstData.directLink} (成功 ${directCount} 个字段)`); await delay(300); if (firstData.isIOS) { const h5Count = setInputValue(selectors.h5Link, firstData.h5Link); addLog(`检测到iOS,填充H5链接: ${firstData.h5Link} (成功 ${h5Count} 个字段)`); } message.success("表单填充完成"); addLog("批量填充操作完成"); } catch (error) { console.error("填充表单失败:", error); message.error("填充表单失败: " + error.message); addLog("填充失败: " + error.message); } finally { isProcessing.value = false; } }; const sendEmail = async (to, subject, content) => { if (!emailConfig.value.apiKey) { throw new Error("请先配置SendGrid API Key"); } const data = { personalizations: [{ to: [{ email: to }], subject }], from: { email: emailConfig.value.fromEmail || "[email protected]" }, content: [{ type: "text/plain", value: content }] }; try { const response = await fetch("https://api.sendgrid.com/v3/mail/send", { method: "POST", headers: { "Authorization": `Bearer ${emailConfig.value.apiKey}`, "Content-Type": "application/json" }, body: JSON.stringify(data) }); if (!response.ok) { throw new Error(`邮件发送失败: ${response.status}`); } return true; } catch (error) { console.error("邮件发送错误:", error); throw error; } }; const testEmail = async () => { if (!emailConfig.value.toEmails) { message.warning("请先配置接收邮箱"); return; } isSendingEmail.value = true; try { const emails = emailConfig.value.toEmails.split(",").map((email) => email.trim()); const subject = "快手广告工具 - 测试邮件"; const content = `这是一封来自快手广告填表工具的测试邮件。 发送时间: ${(/* @__PURE__ */ new Date()).toLocaleString()}`; for (const email of emails) { await sendEmail(email, subject, content); addLog(`测试邮件已发送到: ${email}`); } message.success("测试邮件发送成功"); } catch (error) { console.error("发送测试邮件失败:", error); message.error("发送测试邮件失败: " + error.message); addLog("邮件发送失败: " + error.message); } finally { isSendingEmail.value = false; } }; const clearData = () => { const keys = ["batchData", "apiKey", "fromEmail", "toEmails"]; keys.forEach((key) => { localStorage.removeItem(`ks_${key}`); }); formData.value.batchData = ""; emailConfig.value.apiKey = ""; emailConfig.value.fromEmail = ""; emailConfig.value.toEmails = ""; parsedData.value = []; logs.value = []; message.success("已清除所有数据"); }; return (_ctx, _cache) => { const _component_n_input = vue.resolveComponent("n-input"); const _component_n_text = vue.resolveComponent("n-text"); const _component_n_form_item = vue.resolveComponent("n-form-item"); const _component_n_space = vue.resolveComponent("n-space"); const _component_n_collapse_item = vue.resolveComponent("n-collapse-item"); const _component_n_collapse = vue.resolveComponent("n-collapse"); const _component_n_button = vue.resolveComponent("n-button"); const _component_n_grid_item = vue.resolveComponent("n-grid-item"); const _component_n_grid = vue.resolveComponent("n-grid"); const _component_n_tag = vue.resolveComponent("n-tag"); const _component_n_table = vue.resolveComponent("n-table"); const _component_n_log = vue.resolveComponent("n-log"); const _component_n_card = vue.resolveComponent("n-card"); return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [ vue.createVNode(_component_n_card, { title: "快手广告填表工具", class: "tool-card" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_space, { vertical: "", size: 16 }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_form_item, { label: "批量数据输入" }, { feedback: vue.withCtx(() => [ vue.createVNode(_component_n_text, { depth: "3", style: { "font-size": "12px" } }, { default: vue.withCtx(() => _cache[8] || (_cache[8] = [ vue.createTextVNode(" 格式示例:广告计划名称-IOS https://example.com market://details?id=com.app ", -1) ])), _: 1, __: [8] }) ]), default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: formData.value.batchData, "onUpdate:value": [ _cache[0] || (_cache[0] = ($event) => formData.value.batchData = $event), _cache[1] || (_cache[1] = ($event) => saveToLocalStorage("batchData", $event)) ], type: "textarea", placeholder: "请按格式输入:标题名称[TAB]H5链接[TAB]直达链接,每行一条数据", autosize: { minRows: 4, maxRows: 8 } }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_collapse, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_collapse_item, { title: "邮件通知设置", name: "email" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_space, { vertical: "" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_form_item, { label: "SendGrid API Key" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: emailConfig.value.apiKey, "onUpdate:value": [ _cache[2] || (_cache[2] = ($event) => emailConfig.value.apiKey = $event), _cache[3] || (_cache[3] = ($event) => saveToLocalStorage("apiKey", $event)) ], type: "password", placeholder: "请输入SendGrid API Key" }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_form_item, { label: "发送邮箱" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: emailConfig.value.fromEmail, "onUpdate:value": [ _cache[4] || (_cache[4] = ($event) => emailConfig.value.fromEmail = $event), _cache[5] || (_cache[5] = ($event) => saveToLocalStorage("fromEmail", $event)) ], placeholder: "请输入发送邮箱地址" }, null, 8, ["value"]) ]), _: 1 }), vue.createVNode(_component_n_form_item, { label: "接收邮箱" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_input, { value: emailConfig.value.toEmails, "onUpdate:value": [ _cache[6] || (_cache[6] = ($event) => emailConfig.value.toEmails = $event), _cache[7] || (_cache[7] = ($event) => saveToLocalStorage("toEmails", $event)) ], placeholder: "请输入接收邮箱,多个用逗号分隔" }, null, 8, ["value"]) ]), _: 1 }) ]), _: 1 }) ]), _: 1 }) ]), _: 1 }), vue.createVNode(_component_n_grid, { cols: 2, "x-gap": 12, "y-gap": 12 }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "primary", block: "", size: "large", onClick: fillFormData, loading: isProcessing.value }, { icon: vue.withCtx(() => _cache[9] || (_cache[9] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "✏️", -1) ])), default: vue.withCtx(() => [ _cache[10] || (_cache[10] = vue.createTextVNode(" 批量填充表单 ", -1)) ]), _: 1, __: [10] }, 8, ["loading"]) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "info", block: "", size: "large", onClick: testEmail, loading: isSendingEmail.value }, { icon: vue.withCtx(() => _cache[11] || (_cache[11] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "📧", -1) ])), default: vue.withCtx(() => [ _cache[12] || (_cache[12] = vue.createTextVNode(" 发送测试邮件 ", -1)) ]), _: 1, __: [12] }, 8, ["loading"]) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "warning", block: "", size: "large", onClick: clearData }, { icon: vue.withCtx(() => _cache[13] || (_cache[13] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "🗑️", -1) ])), default: vue.withCtx(() => [ _cache[14] || (_cache[14] = vue.createTextVNode(" 清除所有数据 ", -1)) ]), _: 1, __: [14] }) ]), _: 1 }), vue.createVNode(_component_n_grid_item, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_button, { type: "success", block: "", size: "large", onClick: previewData }, { icon: vue.withCtx(() => _cache[15] || (_cache[15] = [ vue.createElementVNode("span", { style: { "font-size": "16px" } }, "👁️", -1) ])), default: vue.withCtx(() => [ _cache[16] || (_cache[16] = vue.createTextVNode(" 预览解析数据 ", -1)) ]), _: 1, __: [16] }) ]), _: 1 }) ]), _: 1 }), parsedData.value.length > 0 ? (vue.openBlock(), vue.createBlock(_component_n_collapse, { key: 0 }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_collapse_item, { title: "数据预览", name: "preview" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_table, { bordered: false, "single-line": false, size: "small" }, { default: vue.withCtx(() => [ _cache[17] || (_cache[17] = vue.createElementVNode("thead", null, [ vue.createElementVNode("tr", null, [ vue.createElementVNode("th", null, "序号"), vue.createElementVNode("th", null, "标题名称"), vue.createElementVNode("th", null, "H5链接"), vue.createElementVNode("th", null, "直达链接"), vue.createElementVNode("th", null, "是否iOS") ]) ], -1)), vue.createElementVNode("tbody", null, [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(parsedData.value, (item, index) => { return vue.openBlock(), vue.createElementBlock("tr", { key: index }, [ vue.createElementVNode("td", null, vue.toDisplayString(index + 1), 1), vue.createElementVNode("td", null, vue.toDisplayString(item.title), 1), vue.createElementVNode("td", null, vue.toDisplayString(item.h5Link), 1), vue.createElementVNode("td", null, vue.toDisplayString(item.directLink), 1), vue.createElementVNode("td", null, [ vue.createVNode(_component_n_tag, { type: item.isIOS ? "success" : "default", size: "small" }, { default: vue.withCtx(() => [ vue.createTextVNode(vue.toDisplayString(item.isIOS ? "iOS" : "普通"), 1) ]), _: 2 }, 1032, ["type"]) ]) ]); }), 128)) ]) ]), _: 1, __: [17] }) ]), _: 1 }) ]), _: 1 })) : vue.createCommentVNode("", true), logs.value.length > 0 ? (vue.openBlock(), vue.createBlock(_component_n_collapse, { key: 1 }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_collapse_item, { title: "操作日志", name: "logs" }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_log, { log: logs.value.join("\n"), rows: 6 }, null, 8, ["log"]) ]), _: 1 }) ]), _: 1 })) : vue.createCommentVNode("", true) ]), _: 1 }) ]), _: 1 }) ]); }; } }; const kuaishou = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-7227acb7"]]); const _sfc_main = { __name: "App", setup(__props) { const active = vue.ref(false); const placement = vue.ref("right"); const activate = (place) => { active.value = true; placement.value = place; }; const currentComponent = vue.computed(() => { const url = window.location.href; if (url.includes("xiaohongshu.com") || url.includes("xhslink.com")) { return XHS; } if (url.includes("galaxy.alibaba-inc.com")) { return zt; } if (url.includes("ad.e.kuaishou.com")) { return kuaishou; } return DefaultComponent; }); return (_ctx, _cache) => { const _component_n_icon = vue.resolveComponent("n-icon"); const _component_n_float_button = vue.resolveComponent("n-float-button"); const _component_n_drawer_content = vue.resolveComponent("n-drawer-content"); const _component_n_drawer = vue.resolveComponent("n-drawer"); const _component_n_message_provider = vue.resolveComponent("n-message-provider"); return vue.openBlock(), vue.createBlock(_component_n_message_provider, null, { default: vue.withCtx(() => [ vue.createVNode(_component_n_float_button, { type: "primary", position: "fixed", right: 24, bottom: 24, onClick: _cache[0] || (_cache[0] = ($event) => activate("right")) }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_icon, null, { default: vue.withCtx(() => _cache[2] || (_cache[2] = [ vue.createTextVNode(" 🐒 ", -1) ])), _: 1, __: [2] }) ]), _: 1 }), vue.createVNode(_component_n_drawer, { show: active.value, "onUpdate:show": _cache[1] || (_cache[1] = ($event) => active.value = $event), width: 502, placement: placement.value }, { default: vue.withCtx(() => [ vue.createVNode(_component_n_drawer_content, { title: "工具箱 by.qjj" }, { default: vue.withCtx(() => [ _cache[3] || (_cache[3] = vue.createTextVNode(" 通用工具箱 ", -1)), (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(currentComponent.value))) ]), _: 1, __: [3] }) ]), _: 1 }, 8, ["show", "placement"]) ]), _: 1 }); }; } }; if (window.self === window.top) { vue.createApp(_sfc_main).use(naive).mount( (() => { const app = document.createElement("div"); app.style.position = "absolute"; app.style.top = "0"; app.style.left = "0"; app.style.zIndex = "10000"; document.body.append(app); return app; })() ); } else { console.log("在 iframe 中,不加载应用"); } } }); require_main_001(); })(Vue, naive);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址