From 9348d52a988b50af94b3e41a7208339d04feae5c Mon Sep 17 00:00:00 2001 From: personal82555 Date: Tue, 20 Oct 2026 18:57:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B4=AD=E4=B9=B0=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E9=87=8D=E5=81=9A=EF=BC=88=E6=96=B0=E9=A1=B5=E9=80=89=E5=A5=97?= =?UTF-8?q?=E9=A4=90=E2=86=92=E9=80=89=E6=94=AF=E4=BB=98=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=EF=BC=89+=20=E6=94=AF=E4=BB=98=E5=90=8E=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=BF=80=E6=B4=BB=20v1.8.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复「点击购买授权没反应」:支付方式选择行被 .pay-select-row 的 display:flex 压过 hidden 属性常驻显示;新增全局 [hidden]{display:none!important} - 点「购买授权」改为打开新页面 buy.html:①展示本项目全部在售套餐 ②选套餐后才显示支付方式 ③下单支付 - 自动激活改为后台 chrome.alarms 每分钟轮询(关掉侧边栏/支付页也能激活),侧边栏轮询保留为快速通道 - authCreateOrder 支持传入所选套餐 cardTypeId;新增 getCardTypes 消息 --- README.md | 12 ++- background.js | 65 +++++++++++-- buy.css | 256 +++++++++++++++++++++++++++++++++++++++++++++++++ buy.html | 46 +++++++++ buy.js | 140 +++++++++++++++++++++++++++ manifest.json | 2 +- privacy.html | 2 +- sidepanel.css | 35 ++----- sidepanel.html | 9 +- sidepanel.js | 47 +-------- 10 files changed, 522 insertions(+), 92 deletions(-) create mode 100644 buy.css create mode 100644 buy.html create mode 100644 buy.js diff --git a/README.md b/README.md index d99e3dc..878e856 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > 一键搜索 · 自动点击 · 智能评论 —— 小红书运营引流的效率神器 -[![版本](https://img.shields.io/badge/版本-1.7.9-ff2442.svg)](https://dl.88531.cn/xhs.html) +[![版本](https://img.shields.io/badge/版本-1.8.0-ff2442.svg)](https://dl.88531.cn/xhs.html) [![平台](https://img.shields.io/badge/平台-Chrome%20%7C%20Edge-4caf50.svg)](#安装方法) [![语言](https://img.shields.io/badge/语言-纯%20JavaScript-2196f3.svg)](#开发说明) @@ -104,10 +104,16 @@ ## 📜 版本历史 -当前版本:**1.7.9** +当前版本:**1.8.0**
-展开查看完整变更记录(v1.2.0 ~ v1.7.9) +展开查看完整变更记录(v1.2.0 ~ v1.8.0) + +### 1.8.0 +- **购买流程重做**:点「购买授权」不再原地展开支付方式,而是**打开新页面** → ① 展示本项目全部在售套餐供选择 → ② 选套餐后才出现支付方式(支付宝/微信)→ ③ 下单支付,支付成功**自动发卡并激活本机** +- **支付后必定自动激活**:订单轮询从侧边栏搬到后台定时任务,**关掉侧边栏、关掉购买页、甚至重启浏览器**都能在支付完成后自动完成激活,不再出现「付了钱还显示未授权」 +- **修复「点击购买授权没反应」**:支付方式选择行此前被 CSS 常驻显示(`display:flex` 压过了 `hidden` 属性),点击后视觉上毫无变化;现已修复,选择行默认隐藏、按需展开 +- 套餐与价格实时读取服务端在售列表(不再写死金额),购买页会跳过 0 元测试套餐 ### 1.7.9 - **试用策略升级「72 小时 + 100 条」**:时间与条数先到先停——拉长试用必须配用量上限,避免长时间白嫖评论量 diff --git a/background.js b/background.js index 96e1560..4658c8d 100644 --- a/background.js +++ b/background.js @@ -16,7 +16,7 @@ const DEFAULT_AI = { const AUTH_BASE = 'https://auth.88531.cn'; const AUTH_PROJECT_ID = 3; const AUTH_API_KEY = 'ak_bbf83b76df8219388d7f60b9e67c7db2'; -const CLIENT_VERSION = '1.7.9'; +const CLIENT_VERSION = '1.8.0'; const TRIAL_MS = 72 * 60 * 60 * 1000; // 试用 72 小时(3 天) const TRIAL_QUOTA = 100; // 试用期最多 100 条评论(时间/条数先到先停,防止白嫖薅量) const GRACE_DAILY = 3; // 试用到期不硬锁:每天保留 3 条体验额度 @@ -210,6 +210,13 @@ async function authOnInstalled() { } catch (error) { console.error('启动时授权复验失败:', error); } + + // 有未完成订单则恢复后台轮询(支付后自动激活不依赖侧边栏是否开着) + try { + await scheduleOrderPolling(); + } catch (error) { + console.error('恢复订单轮询失败:', error); + } } // 注册定时任务:心跳/复验/公告/更新检查 @@ -234,6 +241,8 @@ chrome.alarms?.onAlarm?.addListener(async (alarm) => { await authGetAnnouncements(); } else if (alarm.name === 'authUpdateCheck') { await authCheckUpdate(); + } else if (alarm.name === 'orderPoll') { + await pollPendingOrder(); } } catch (error) { console.error('授权定时任务失败:', alarm.name, error); @@ -459,16 +468,19 @@ async function usageTick() { } // 创建购买订单(contact_info 带机器码 → 支付成功后系统自动发卡绑定) -async function authCreateOrder(payType) { +async function authCreateOrder(payType, cardTypeId) { const pay = payType === 'wxpay' ? 'wxpay' : 'alipay'; - - // 取项目第一个套餐 + + // 读取在售套餐:购买页选定 cardTypeId 时用选中的,否则取第一个(兼容旧调用) const typesRes = await authFetch(`/api/public/projects/${AUTH_PROJECT_ID}/card-types`); if (!typesRes.ok || !Array.isArray(typesRes.data) || typesRes.data.length === 0) { return { ok: false, message: '暂无在售套餐,请稍后再试' }; } - const cardType = typesRes.data[0]; - + const cardType = (cardTypeId ? typesRes.data.find((t) => String(t.id) === String(cardTypeId)) : null) + || typesRes.data.find((t) => Number(t.price) > 0) + || typesRes.data[0]; + if (!cardType) return { ok: false, message: '套餐不存在,请重新选择' }; + const machineId = await getDeviceId(); const price = Number(cardType.price); // 试用到期 24 小时内下单自动带限时优惠码(服务端按折扣重算实付金额) @@ -510,8 +522,34 @@ async function authCreateOrder(payType) { createdAt: Date.now() }; await chrome.storage.local.set({ pendingOrder }); - - return { ok: true, order: pendingOrder, payUrl: res.data.pay_url }; + await scheduleOrderPolling(); + + return { ok: true, order: pendingOrder, payUrl: res.data.pay_url, cardTypeName: cardType.name }; +} + +// 后台订单轮询:侧边栏/购买页关闭也能完成「支付 → 自动发卡 → 自动激活」 +async function scheduleOrderPolling() { + if (!chrome.alarms) return; + const { pendingOrder } = await chrome.storage.local.get(['pendingOrder']); + if (!pendingOrder || !pendingOrder.orderNo) return; + await chrome.alarms.create('orderPoll', { periodInMinutes: 1 }); +} + +async function pollPendingOrder() { + const { pendingOrder } = await chrome.storage.local.get(['pendingOrder']); + if (!pendingOrder || !pendingOrder.orderNo) { + try { await chrome.alarms.clear('orderPoll'); } catch (e) { /* 无该 alarm */ } + return; + } + try { + const result = await authQueryOrder(pendingOrder.orderNo); + if (result && result.activated) { + await chrome.storage.local.remove(['pendingOrder']); + try { await chrome.alarms.clear('orderPoll'); } catch (e) { /* 无该 alarm */ } + } + } catch (error) { + console.error('后台订单轮询失败:', error); + } } // 查询订单(支付+自动发卡后返回 card_key;拿到卡密自动激活) @@ -586,7 +624,16 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { } if (request.action === 'authCreateOrder') { - authCreateOrder(request.payType).then((res) => sendResponse(res)); + authCreateOrder(request.payType, request.cardTypeId).then((res) => sendResponse(res)); + return true; + } + + if (request.action === 'getCardTypes') { + authFetch(`/api/public/projects/${AUTH_PROJECT_ID}/card-types`).then((res) => { + sendResponse({ ok: !!res.ok, data: res.data || [], message: res.message }); + }).catch((error) => { + sendResponse({ ok: false, message: error.message, data: [] }); + }); return true; } diff --git a/buy.css b/buy.css new file mode 100644 index 0000000..b367ef6 --- /dev/null +++ b/buy.css @@ -0,0 +1,256 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif; + background: #f6f7f9; + color: #222; + min-height: 100vh; +} + +.page { + max-width: 720px; + margin: 0 auto; + padding: 28px 18px 40px; +} + +.head { + text-align: center; + margin-bottom: 26px; +} + +.logo { + display: inline-block; + font-size: 12px; + color: #fff; + background: #ff2442; + border-radius: 20px; + padding: 4px 14px; + margin-bottom: 12px; +} + +.head h1 { + font-size: 26px; + margin-bottom: 10px; +} + +.flow { + font-size: 13px; + color: #888; +} + +section { + background: #fff; + border-radius: 12px; + padding: 20px; + margin-bottom: 16px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); +} + +h2 { + font-size: 17px; + margin-bottom: 16px; + display: flex; + align-items: center; + gap: 10px; +} + +.num { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 50%; + background: #ff2442; + color: #fff; + font-size: 13px; + flex: none; +} + +.package-list { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 14px; +} + +.package { + border: 2px solid #eee; + border-radius: 10px; + padding: 16px 14px; + text-align: center; + cursor: pointer; + transition: all 0.18s ease; +} + +.package:hover { + border-color: #ffb3bf; + transform: translateY(-2px); +} + +.package.active { + border-color: #ff2442; + background: #fff6f7; +} + +.pkg-name { + font-size: 15px; + font-weight: 600; + margin-bottom: 8px; +} + +.pkg-price { + font-size: 24px; + font-weight: 700; + color: #ff2442; + margin-bottom: 6px; +} + +.pkg-dur { + font-size: 12px; + color: #999; + margin-bottom: 12px; +} + +.pkg-btn { + width: 100%; + padding: 8px 0; + border: none; + border-radius: 6px; + background: #ff2442; + color: #fff; + font-size: 13px; + cursor: pointer; + transition: background 0.18s ease; +} + +.pkg-btn:hover { + background: #e01030; +} + +.package.active .pkg-btn { + background: #e01030; +} + +.loading, +.empty { + grid-column: 1 / -1; + text-align: center; + color: #999; + font-size: 13px; + padding: 24px 0; +} + +.chosen { + font-size: 13px; + color: #666; + margin-bottom: 14px; +} + +.chosen b { + color: #ff2442; +} + +.pay-methods { + display: flex; + gap: 14px; +} + +.pay-btn { + flex: 1; + padding: 14px 0; + border: 2px solid #eee; + border-radius: 10px; + background: #fff; + font-size: 15px; + cursor: pointer; + transition: all 0.18s ease; +} + +.pay-btn.alipay { + color: #1677ff; + border-color: #bcd6ff; +} + +.pay-btn.wxpay { + color: #09bb07; + border-color: #b6e6b8; +} + +.pay-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.pay-btn.alipay:hover { + border-color: #1677ff; +} + +.pay-btn.wxpay:hover { + border-color: #09bb07; +} + +.tip { + margin-top: 12px; + font-size: 12px; + color: #999; +} + +.order-status { + font-size: 14px; + line-height: 1.8; + padding: 14px; + border-radius: 8px; + background: #f6f7f9; + word-break: break-all; +} + +.order-status.pending { + color: #b26a00; + background: #fff8e6; +} + +.order-status.error { + color: #c62828; + background: #fdecea; +} + +.order-status.success { + color: #1b5e20; + background: #eef7ee; +} + +.ok-title { + font-size: 16px; + font-weight: 700; + margin-bottom: 8px; +} + +.ok-line { + font-size: 13px; + margin-bottom: 4px; +} + +.ok-line b { + color: #1b5e20; +} + +.muted { + color: #999; + font-size: 12px; +} + +.foot { + text-align: center; + font-size: 12px; + color: #999; + line-height: 1.9; +} + +.foot a { + color: #ff2442; + text-decoration: none; +} diff --git a/buy.html b/buy.html new file mode 100644 index 0000000..0c493f2 --- /dev/null +++ b/buy.html @@ -0,0 +1,46 @@ + + + + + +购买授权 · 小红书自动评论助手 + + + +
+
+ +

购买授权

+

① 选择套餐 → ② 选择支付方式 → ③ 完成支付(支付成功自动激活本机)

+
+ +
+
+

1 选择套餐

+
+
+ + + + +
+ + +
+ + + diff --git a/buy.js b/buy.js new file mode 100644 index 0000000..d828d63 --- /dev/null +++ b/buy.js @@ -0,0 +1,140 @@ +/* 购买授权页:选套餐 → 选支付方式 → 下单 → 支付 → 自动激活 */ +const $ = (id) => document.getElementById(id); +let packages = []; +let selected = null; +let orderNo = null; +let pollTimer = null; + +function esc(s) { + return String(s == null ? '' : s).replace(/[&<>"']/g, (c) => ({ + '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' + }[c])); +} + +function durationText(days) { + const n = Number(days); + if (!n) return '限时体验'; + if (n >= 999999) return '永久有效'; + return n + ' 天'; +} + +async function loadPackages() { + $('package-list').innerHTML = '
正在加载套餐…
'; + try { + const res = await chrome.runtime.sendMessage({ action: 'getCardTypes' }); + if (!res || !res.ok) throw new Error((res && res.message) || '加载失败'); + packages = (res.data || []).filter((p) => Number(p.price) > 0); + if (!packages.length) { + $('package-list').innerHTML = '
暂无在售套餐,请稍后再试
'; + return; + } + renderPackages(); + } catch (e) { + $('package-list').innerHTML = '
套餐加载失败:' + esc(e.message) + '
'; + } +} + +function renderPackages() { + $('package-list').innerHTML = packages.map((p) => ` +
+
${esc(p.name)}
+
¥${esc(p.price)}
+
${esc(durationText(p.duration_days))}
+ +
`).join(''); + document.querySelectorAll('.pkg-btn').forEach((btn) => { + btn.addEventListener('click', () => selectPackage(btn.dataset.id)); + }); +} + +function selectPackage(id) { + selected = packages.find((p) => String(p.id) === String(id)); + if (!selected) return; + document.querySelectorAll('.package').forEach((el) => { + el.classList.toggle('active', el.dataset.id === String(id)); + }); + $('chosen-package').innerHTML = `已选套餐:${esc(selected.name)} 价格 ¥${esc(selected.price)} ${esc(durationText(selected.duration_days))}`; + $('step-pay').hidden = false; + $('step-pay').scrollIntoView({ behavior: 'smooth', block: 'center' }); +} + +async function createOrder(payType) { + if (!selected) return; + $('order-panel').hidden = false; + $('order-panel').scrollIntoView({ behavior: 'smooth', block: 'center' }); + const status = $('order-status'); + status.className = 'order-status pending'; + status.textContent = '⏳ 正在创建订单…'; + try { + const res = await chrome.runtime.sendMessage({ + action: 'authCreateOrder', + payType, + cardTypeId: selected.id + }); + if (!res || !res.ok) throw new Error((res && res.message) || '创建订单失败'); + + orderNo = res.order.orderNo; + const priceText = res.order.couponCode + ? `¥${res.order.amount}(原价 ¥${res.order.originalPrice},已用优惠码 ${res.order.couponCode})` + : `¥${res.order.amount}`; + status.textContent = `订单 ${orderNo}(${priceText})已创建,正在打开支付页面…`; + if (res.payUrl) window.open(res.payUrl, '_blank'); + startPolling(); + } catch (e) { + status.className = 'order-status error'; + status.textContent = '✗ ' + e.message; + } +} + +function startPolling() { + if (pollTimer) clearInterval(pollTimer); + let attempts = 0; + pollTimer = setInterval(async () => { + attempts++; + if (attempts > 240) { + clearInterval(pollTimer); + pollTimer = null; + const status = $('order-status'); + status.className = 'order-status error'; + status.textContent = `✗ 等待支付超时。订单号 ${orderNo},如已付款请把订单号发给客服QQ 1556688283 手动补发。`; + return; + } + try { + const res = await chrome.runtime.sendMessage({ action: 'authQueryOrder', orderNo }); + if (!res || !res.ok) return; + if (res.activated) { + clearInterval(pollTimer); + pollTimer = null; + showActivated(res); + } else if (res.cardKey && !res.activated) { + clearInterval(pollTimer); + pollTimer = null; + const status = $('order-status'); + status.className = 'order-status error'; + status.textContent = '✗ 已支付但激活失败:' + ((res.licenseState && res.licenseState.message) || '请把订单号发给客服手动处理'); + } else { + const status = $('order-status'); + status.className = 'order-status pending'; + status.textContent = `⏳ 等待支付中…(订单 ${orderNo},已等待 ${attempts * 5} 秒)`; + } + } catch (e) { + /* 单次查询失败不中断轮询 */ + } + }, 5000); +} + +function showActivated(res) { + const status = $('order-status'); + status.className = 'order-status success'; + status.innerHTML = ` +
✓ 支付成功,已自动激活
+
卡密:${esc(res.cardKey || '')}
+
到期时间:${esc(res.expireTime || '永久')}
+
回到插件侧边栏即可使用全部功能(本机已授权)。
`; +} + +document.querySelectorAll('.pay-btn').forEach((btn) => { + btn.addEventListener('click', () => createOrder(btn.dataset.pay)); +}); + +loadPackages(); diff --git a/manifest.json b/manifest.json index bad9533..55c75d3 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "小红书自动评论助手", - "version": "1.7.9", + "version": "1.8.0", "description": "右侧侧边栏常驻的自动评论助手,支持试用/卡密授权、固定池/自定义文字/图片/AI评论", "permissions": [ "storage", diff --git a/privacy.html b/privacy.html index 0a11b91..263edc7 100644 --- a/privacy.html +++ b/privacy.html @@ -16,7 +16,7 @@

小红书自动评论助手 · 隐私政策

-
生效日期:2026年10月10日 · 适用版本:v1.7.9 及以上
+
生效日期:2026年10月10日 · 适用版本:v1.8.0 及以上

感谢使用「小红书自动评论助手」浏览器扩展(以下简称"本插件")。我们重视你的隐私。本页面说明本插件收集哪些信息、如何使用以及如何保护。

diff --git a/sidepanel.css b/sidepanel.css index 17f3f89..2a1a18b 100644 --- a/sidepanel.css +++ b/sidepanel.css @@ -894,35 +894,11 @@ body { background: linear-gradient(135deg, #f57c00, #ff9800); } -.pay-select-row { - display: flex; - align-items: center; - gap: 8px; +.buy-hint { margin-top: 8px; -} - -.pay-select-label { font-size: 12px; - color: #666; -} - -.pay-btn { - padding: 6px 12px; - border: 1px solid #ddd; - border-radius: 6px; - background: #fff; - font-size: 12px; - cursor: pointer; - transition: all 0.2s ease; -} - -.pay-btn:hover { - border-color: #4caf50; - color: #2e7d32; -} - -.pay-cancel { - color: #999; + line-height: 1.6; + color: #888; } .order-status { @@ -1055,4 +1031,9 @@ body { @keyframes latest-version-pulse { 0%, 100% { box-shadow: 0 4px 14px rgba(255, 36, 66, 0.45); } 50% { box-shadow: 0 4px 22px rgba(255, 36, 66, 0.75); } +} + +/* hidden 属性必须压过 display:flex 等规则,否则元素常驻显示(购买授权点了没反应即此原因) */ +[hidden] { + display: none !important; } \ No newline at end of file diff --git a/sidepanel.html b/sidepanel.html index 0a270d3..b32a94a 100644 --- a/sidepanel.html +++ b/sidepanel.html @@ -26,12 +26,7 @@ ⏰ 试用到期限时优惠:码 XHS24H · 8 折 · 剩余 --:--:-- - +
点击「购买授权」将在新页面选择套餐与支付方式,支付成功后本机自动激活。