NoobClaw - 矩阵自动涨粉引擎 AI 驱动 · 日夜无休 · 赚流量赚钱

AI完全模拟人类行为,0风险操作多平台多账号图文/视频批量生成,互动快速涨粉!

高质量原创输出 💰极低成本(日更百条视频,百篇好文<¥25) 🛡️严格反检测,完全拟人(随机抖动间隔) 🛡️完全本地 · 你的浏览器,你的账号 🚀快速涨粉(真实互动 = 粉丝飙升)

核心能力

为什么选 NoobClaw?

解决传统运营工具搞不定的核心痛点

一键安装

无需复杂配置。下载、安装、登录,搞定。提供 Windows & Mac 安装包,开箱即用。

300+ 自动化技能

内置覆盖小红书、抖音、推特、TikTok、YouTube 等主流平台的 300+ 自动化运营技能,图文/视频创作、互动、涨粉、跨平台搬运一站搞定。

解放双手,后台跑

设好任务就不用管,后台拟人化跑,你睡觉它也在涨粉。邀请好友还能拿 6 层返佣。

免 API Key,内置 AI

AI 接口已为你接好,充值积分即可调用,无需自己折腾 OpenAI / Claude / Gemini 等模型对接。

本地运行,反检测稳

在你自己的电脑+浏览器里跑,接管真实账号操作。随机抖动+拟人节奏,封号率远低于云端脚本。

账号自有 · 开源透明

账号 cookie 仅留在你本地浏览器,我们碰不到。全代码透明、零数据收集,可审计、可信任。

📺 视频教程

更多教程

快速上手

工作 原理

三步极速上手

1

下载安装

下载 NoobClaw 桌面客户端(Windows / macOS),一键安装,无需任何前置依赖。

2

登录平台

在客户端内打开小红书 / 抖音 / 推特 / TikTok / YouTube,正常登录你的账号——Cookie 全程留在本地浏览器。

3

启动 AI

在技能商店挑选图文/视频创作、互动、涨粉等任务,一键启动,AI 自动接管,后台拟人跑。

应用场景

使用 场景

AI 驱动的多平台图文/视频运营自动化

自动涨粉

小红书 / 抖音 / 推特 / TikTok / YouTube 跨平台自动发图文/视频、回评、点赞、关注。真实互动 + 随机抖动节奏,安全稳健地涨粉。

一键多平台图文/视频

同一篇图文/视频自动适配各平台风格,一键同时发布到小红书 / 抖音 / 推特 / TikTok / YouTube,题图、话题、@艾特全自动处理。

跨平台内容搬运

从推特 / 小红书 / 抖音 / TikTok / YouTube 抓优质爆款内容,AI 改写去重,自动发到你的目标平台。视频自动重新合成,图文自动重排。

热点话题追踪

实时抓取各平台热搜榜、爆款话题、行业动态,自动推送给你或直接生成贴文跟热点。

对标账号追更

监控你定的对标博主,新发内容第一时间拉取、AI 改写、自动跟发,踩中爆款节奏不漏。

数据看板

所有账号、平台的发布数、互动率、涨粉曲线一屏汇总,效果一目了然,自动出周报。

AI 自动回评

粉丝/评论区互动 24 小时不掉线,AI 根据语境生成自然回复,引流转私域、放大爆款流量。

消息通知

任务完成、爆款命中、异常告警 通过 微信 / 飞书 / Telegram 实时推送,出门也能盯盘。

定时任务

按你定的时间表自动发文 / 互动 / 跟热点。错峰发布、节假日预排,养号节奏稳。

立即下载

下载 NoobClaw

支持 Windows / macOS。客户端全代码透明,安全可信。

生态

活动与 合作伙伴

更多活动与合作伙伴陆续上线...

: '¥'; const months = SUB_PERIOD_MONTHS[_subPeriod] || 1; const pl = SUB_PERIOD_LABEL[_subPeriod] || { z: '', e: '' }; // 银行卡渠道:只放开 Dodo 后台真有 product 的周期。半年档没建 → 置灰, // 否则用户点了会开出一张永远收不到钱的单(后端也会拒 DODO_PLAN_UNAVAILABLE)。 const dodoHasPeriod = (pk) => !_subDodoPlans.length || _subDodoPlans.some(x => String(x).endsWith(':' + pk)); const periodTabs = SUB_PERIODS.map(p => { const off = _subMethod === 'DODO' && !dodoHasPeriod(p.k); if (off) return ``; return ``; }).join(''); const cards = sorted.map(plan => { const isFree = plan.code === 'free'; const isCur = plan.code === curCode; const isCurActive = subActive && isCur; const isLower = subActive && (plan.sort_order || 0) < curOrder; const isRec = plan.code === SUB_RECOMMENDED; const price = (plan.prices && plan.prices[_subPeriod]) || {}; const tier = SUB_TIER_COLOR[plan.code] || '#9aa0aa'; const discount = (price.discount != null) ? price.discount : 1; const finalP = isFree ? 0 : (price.cny != null ? price.cny : plan.price_cny); const origP = plan.price_cny * months; const hasDiscount = !isFree && discount < 0.999; const off = Math.round(discount * 100) / 10; // 0.7→7 折 const cta = isCurActive ? '续费' : (subActive ? '升级' : '订阅'); let btn; if (isLower) btn = ``; else if (isFree) btn = ``; // 微信通道可用 → 主按钮直接微信扫码下单(店铺卡密仍可从下方兑换框走);不可用 → 维持去店铺买卡密。 else if (_subWxpayOk) btn = ``; else btn = ``; return `
${isRec ? `最受欢迎` : ''}
${planName(plan)} ${hasDiscount ? `限时${off}折` : ''}
${sym}${finalP} ${hasDiscount ? `${sym}${Math.round(origP)}` : ''} ${!isFree ? `/${pl.z}` : ''}
${btn}
`; }).join(''); const usageBar = subActive && monthly > 0 ? `
本月用量${usedPct}%
` : ''; // CNY 兑换码框(国内版常驻):店铺买卡密 → 回来输入开通对应档位/周期。 const redeemBox = `
会员兑换码
在店铺购买会员码后,在此输入兑换即可开通对应档位与周期。
`; _subRootEl().innerHTML = _subWrap(`

会员订阅

订阅赠送的算力按月发放、到期清零;充值的算力永久有效、不受影响。到期需手动续费。

当前: ${curPlan ? planName(curPlan) : '免费版'} ${subActive && cur.periodEnd ? `到期 ${new Date(cur.periodEnd).toLocaleDateString()}` : ''}
${usageBar}
${periodTabs}
${cards}
${redeemBox}

订阅赠送的算力按月发放、到期清零。

`); } // 会员兑换码核销:preview 拉信息 → 二次确认 → /api/redeem 核销 → 刷新订阅页。 window.subRedeem = async function () { const input = document.getElementById('sub-redeem-input'); const btn = document.getElementById('sub-redeem-btn'); const msg = document.getElementById('sub-redeem-msg'); if (!input || !msg) return; const code = input.value.trim(); if (!code) { msg.textContent = '请输入卡密'; msg.style.color = '#ef4444'; return; } const token = localStorage.getItem('noobclaw_token'); if (btn) btn.disabled = true; msg.textContent = ''; msg.style.color = ''; try { const pRes = await fetch(API_BASE + '/api/redeem/preview', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + (token || '') }, body: JSON.stringify({ code }) }); const preview = await pRes.json(); if (!pRes.ok || !preview.ok) { msg.textContent = preview.message || '查询失败'; msg.style.color = '#ef4444'; return; } const confirmMsg = preview.product_type === 'subscription' ? '此卡密为会员订阅卡,确认开通?(兑换后卡密立刻失效)' : `此卡密面额 ¥${preview.face_value_rmb},可兑换 ${Number(preview.credits).toLocaleString()} 积分。\n\n确认充值?(兑换后卡密立刻失效)`; if (!confirm(confirmMsg)) { msg.textContent = '已取消'; msg.style.color = '#888'; return; } if (btn) btn.textContent = '兑换中...'; const res = await fetch(API_BASE + '/api/redeem', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + (token || '') }, body: JSON.stringify({ code }) }); const d = await res.json(); if (!res.ok || !d.ok) { msg.textContent = d.message || '兑换失败'; msg.style.color = '#ef4444'; return; } alert(d.product_type === 'subscription' ? '会员开通成功!' : '积分已到账!'); subscriptionInit(); } catch (e) { msg.textContent = '网络错误,请重试'; msg.style.color = '#ef4444'; } finally { if (btn) { btn.disabled = false; btn.textContent = '兑换'; } } }; // 微信订阅下单入口(卡片按钮用):切 chain 后走同一个 subBuyPlan。 window.subBuyPlanWx = function (planCode) { _subChain = 'WXPAY'; subBuyPlan(planCode); }; async function subBuyPlan(planCode) { const zh = ucZh(); const res = await ucApi('/api/payment/create', { method: 'POST', body: JSON.stringify({ chain: _subChain, productType: 'subscription', planCode, period: _subPeriod }) }); if (!res || !res.order) { if (res && res.code === 'PENDING_LIMIT') { if (typeof ucShowPendingModal === 'function') ucShowPendingModal(); return; } if (res && res.status === 401) return; const e = document.getElementById('sub-error'); if (e) { e.textContent = (res && res.code === 'TRON_DISABLED') ? (zh ? 'USDT(TRON)通道未配置,请改用 BNB 或联系客服' : 'USDT channel not configured, use BNB or contact support') : (res && String(res.code || '').startsWith('DODO_')) ? ((zh ? '银行卡下单失败' : 'Card payment failed') + (res.error ? ': ' + res.error : '')) : (res && (res.code === 'WXPAY_DISABLED' || res.code === 'WXPAY_CREATE_FAILED')) ? ((zh ? '微信下单失败' : 'WeChat Pay order failed') + (res.error ? ': ' + res.error : '')) : ((zh ? '创建订单失败' : 'Failed to create order') + (res && res.error ? ': ' + res.error : (res && res.status ? ' (HTTP ' + res.status + ')' : (res ? '' : (zh ? '(网络错误/服务无响应)' : ' (network error)'))))); e.classList.remove('hidden'); } return; } const order = res.order; // WXPAY:code_url 挂上 order + 存 localStorage(用户中心「继续支付」能重新出码)。 if (res.codeUrl) { order.wx_code_url = res.codeUrl; try { localStorage.setItem('noobclaw_wxpay_qr', JSON.stringify({ orderNo: order.order_no, codeUrl: res.codeUrl })); } catch (e) { /* quota */ } } // 银行卡:付款在 Dodo 托管的收银台完成 → 开新窗口。入账等 webhook, // 用户付完直接关窗口也能开通,不依赖回跳。 if (res.checkoutUrl) { window.open(res.checkoutUrl, '_blank', 'noopener'); const e2 = document.getElementById('sub-error'); if (e2) { e2.textContent = zh ? '已打开支付页面。付款完成后会员会自动开通,可能需要几秒。' : 'Payment page opened. Your membership activates automatically after payment.'; e2.classList.remove('hidden'); } return; } let addr = res.treasuryWallet || order.deposit_address || ''; if (!addr && _subChain === 'BSC') { const info = await ucApi('/api/payment/info'); addr = (info && info.chains && info.chains.BSC && info.chains.BSC.treasuryWallet) || (info && info.treasuryWallet) || ''; } order.deposit_address = addr; subShowPay(order); } function subShowPay(order) { subClearTimers(); const zh = ucZh(); const isTron = (order.chain || '').toUpperCase() === 'TRON'; const isWx = (order.chain || '').toUpperCase() === 'WXPAY'; // 微信订阅单:金额 ¥(face_value_rmb = plans.price_cny 口径),二维码是微信付款链接。 if (isWx) { const wxAmount = parseFloat(order.face_value_rmb) || 0; const wxCodeUrl = order.wx_code_url || ''; _subRootEl().innerHTML = _subWrap(`
${zh ? '微信扫码支付' : 'Scan with WeChat to pay'}
¥${wxAmount.toFixed(2)}
${wxCodeUrl ? `
QR
${zh ? '请使用手机微信「扫一扫」完成支付' : 'Open WeChat on your phone and scan to pay'}
` : `
${zh ? '二维码已失效,请返回重新下单' : 'QR code unavailable — go back and create a new order'}
`}
${zh ? '支付后自动开通,等待支付确认… ' : 'Activated automatically after payment… '}30:00
`); if (wxCodeUrl) { try { const qr = qrcode(0, 'M'); qr.addData(wxCodeUrl); qr.make(); document.getElementById('sub-pay-qr').src = qr.createDataURL(4, 8); } catch (e) {} } subStartPayTimers(order); return; } const amount = isTron ? parseFloat(order.usdt_amount) : parseFloat(order.bnb_amount); const unit = isTron ? 'USDT' : 'BNB'; const addr = order.deposit_address || ''; _subRootEl().innerHTML = _subWrap(`
${zh ? '订阅支付' : 'Subscription Payment'}
${amount} ${unit}
${zh ? '请转账精确金额(含小数尾数用于自动对账)' : 'Send the exact amount (decimals used for auto-matching)'}
${addr ? `
QR
${isTron ? 'USDT-TRC20' : 'BNB (BSC)'} ${zh ? '收款地址' : 'Address'}
${addr}
` : `
${zh ? '收款地址未配置,请联系客服' : 'Address not configured, contact support'}
`}
${zh ? '转账后自动到账,等待链上确认… ' : 'Auto-credited after transfer… '}30:00
`); if (addr) { try { const qr = qrcode(0, 'M'); qr.addData(addr); qr.make(); document.getElementById('sub-pay-qr').src = qr.createDataURL(4, 8); } catch (e) {} } subStartPayTimers(order); } // 订阅支付面板共用的倒计时 + 状态轮询(链上 / 微信两种面板都走这里)。 function subStartPayTimers(order) { const expireAt = Date.now() + 30 * 60 * 1000; _subPayTimer = setInterval(() => { const rem = Math.max(0, Math.floor((expireAt - Date.now()) / 1000)); const m = Math.floor(rem / 60), s = rem % 60; const el = document.getElementById('sub-pay-cd'); if (el) el.textContent = `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`; if (rem <= 0) { subClearTimers(); const e2 = document.getElementById('sub-pay-cd'); if (e2) e2.textContent = ucZh() ? '已超时' : 'expired'; } }, 1000); _subPollTimer = setInterval(async () => { const st = await ucApi(`/api/payment/status/${order.order_no}`); const status = st && st.order && st.order.status; if (status === 'completed') { subClearTimers(); alert(ucZh() ? '订阅开通成功!' : 'Subscription activated!'); subscriptionInit(); } else if (status === 'failed' || status === 'cancelled' || status === 'expired') { subClearTimers(); subscriptionInit(); } }, 5000); } async function ucBindReferrer() { const zh = ucZh(); let input = document.getElementById('uc-bind-input').value.trim(); const resultEl = document.getElementById('uc-bind-result'); // Extract wallet from link if needed const refMatch = input.match(/[?&]ref=([^&]+)/); if (refMatch) input = refMatch[1]; if (!input || input.length < 10) { resultEl.textContent = zh ? '请输入有效的钱包地址' : 'Invalid wallet address'; resultEl.style.color = '#ff6b6b'; resultEl.classList.remove('hidden'); return; } const res = await ucApi('/api/user/referral/register', { method: 'POST', body: JSON.stringify({ referrerWallet: input }), }); if (res && res.success) { resultEl.textContent = zh ? '绑定成功' : 'Bound successfully'; resultEl.style.color = '#00ff88'; resultEl.classList.remove('hidden'); setTimeout(() => ucInit(), 1000); } else { resultEl.textContent = zh ? '绑定失败,请检查地址' : 'Bind failed'; resultEl.style.color = '#ff6b6b'; resultEl.classList.remove('hidden'); } } function ucSwitchTab(tab) { _ucInviteTab = tab; document.getElementById('uc-tab-records').className = tab === 'records' ? 'px-4 py-2 text-xs font-medium text-neon-green border-b-2 border-neon-green' : 'px-4 py-2 text-xs font-medium text-gray-500 border-b-2 border-transparent hover:text-gray-300'; document.getElementById('uc-tab-rewards').className = tab === 'rewards' ? 'px-4 py-2 text-xs font-medium text-neon-green border-b-2 border-neon-green' : 'px-4 py-2 text-xs font-medium text-gray-500 border-b-2 border-transparent hover:text-gray-300'; if (tab === 'records') ucLoadRecords(); else ucLoadRewards(); } async function ucLoadRecords() { const zh = ucZh(); const data = await ucApi(`/api/user/referral/list?page=${_ucInvitePage}&pageSize=10`); const container = document.getElementById('uc-tab-content'); if (!data || !data.list || data.list.length === 0) { container.innerHTML = emptyStateHtml('👥', zh ? '暂无邀请记录' : 'No invites yet', zh ? '复制上方邀请链接分享给好友,他们注册后会出现在这里。' : 'Copy the invite link above and share it — friends who register will appear here.'); return; } // v1.x: 每条邀请记录后挂一个 L{level} chip,跟客户端 InviteView 同款。 // L1(直接邀请)高亮 neon-green;L2~L6(间接)用灰色弱化。后端 referral/list // 已经返回 level 字段(1~6),空值 fallback "-"。 let html = data.list.map(r => { // 强制数字 + 限定 1..6 — 防御性:r.level 类型定义是 number,但万一后端某次 // 返回字符串 / 非法值,直接拼 `L${lvl}` 会把脏数据塞进 HTML(理论 XSS 面)。 // 拉成整数 + 范围检查后,非法值落到 "-" 分支,渲染干净。 const lvlRaw = Number(r.level); const lvl = (Number.isInteger(lvlRaw) && lvlRaw >= 1 && lvlRaw <= 6) ? lvlRaw : null; const lvlChip = lvl ? (lvl === 1 ? `L1` : `L${lvl}`) : `-`; return `
${r.wallet.slice(0,6)}...${r.wallet.slice(-4)}
${lvlChip} ${new Date(r.createdAt).toLocaleDateString()}
`; }).join(''); const totalPages = Math.max(1, Math.ceil((data.total || 0) / 10)); html += `
${_ucInvitePage}/${totalPages}
`; container.innerHTML = html; } // v1.x: 奖励明细 = USDT 真金返佣 + NoobCoin 空投两条流水,跟客户端 // InviteView 的 Records / Rebate→USDT / Rebate→NOOB 三级结构对齐(网页这边 // 把 USDT / NOOB 作为「奖励明细」内的二级 tab)。USDT 默认选中,因为它是 // 主奖励 (现金返佣 > 代币空投)。 async function ucLoadRewards() { const zh = ucZh(); const container = document.getElementById('uc-tab-content'); // cn 站定位:只展示 CNY 邀请返佣,不显示 USDT/NOOB sub tabs if (cnIsCnSite()) { container.innerHTML = `
`; ucLoadRewardsCny(); return; } const usdtActive = _ucRewardSubTab === 'usdt'; container.innerHTML = `
`; if (usdtActive) ucLoadRewardsUsdt(); else ucLoadRewardsNoob(); } // CNY 邀请返佣明细 — cn 站独享,调 /rebate/earnings?currency=CNY。 // 因为 CNY 没接提现,所有行 status='pending' 直接渲染。 let _ucCnyPage = 1; async function ucLoadRewardsCny() { const zh = ucZh(); const sub = document.getElementById('uc-rewards-sub'); if (!sub) return; const data = await ucApi(`/api/me/rebate/earnings?currency=CNY&page=${_ucCnyPage}&pageSize=10`); if (!data || !data.items || data.items.length === 0) { sub.innerHTML = emptyStateHtml('¥', zh ? '暂无 CNY 邀请返佣记录' : 'No CNY referral rebate yet', zh ? '好友购买卡密充值后,您将获得 CNY 邀请返佣。' : 'When a friend buys a voucher, you earn CNY referral rebate.'); return; } let html = `
${zh?'金额':'Amount'} ${zh?'来源 / 层级':'From / Level'}
${zh?'状态':'Status'} ${zh?'时间':'Time'}
`; html += data.items.map(r => { const amt = Number(r.amount_cny || 0).toFixed(2); const wallet = r.contributor_wallet ? r.contributor_wallet.slice(0,6) + '****' + r.contributor_wallet.slice(-4) : ''; const level = r.level ? 'L'+r.level : ''; return `
+¥${amt} ${wallet} ${level}
⏳ ${zh?'待提现':'pending'} ${new Date(r.earned_at).toLocaleDateString()}
`; }).join(''); const total = data.total || 0; const totalPages = Math.max(1, Math.ceil(total / 10)); html += `
${_ucCnyPage}/${totalPages}
`; sub.innerHTML = html; } function ucSwitchRewardSub(sub) { _ucRewardSubTab = sub; ucLoadRewards(); } // USDT 真金返佣 — 调 /api/me/rebate/earnings (与 client getUsdtRebateEarnings 同源)。 // 每行带 已发放/待发 状态徽章 + 已发放点击可跳 BscScan tx。 // v6.x: 顶部加表头(金额/来源.层级/状态/时间)对齐 client InviteView USDT 表头。 async function ucLoadRewardsUsdt() { const zh = ucZh(); const sub = document.getElementById('uc-rewards-sub'); const data = await ucApi(`/api/me/rebate/earnings?page=${_ucUsdtPage}&pageSize=10`); if (!data || !data.items || data.items.length === 0) { sub.innerHTML = emptyStateHtml('💰', zh ? '暂无 USDT 返佣记录' : 'No USDT rebate yet', zh ? '好友每次充值,你都会按 6 层链路获得 USDT 真金返佣。' : 'Each friend deposit pays you USDT real-cash rebate across the 6-level chain.'); return; } let html = `
${zh?'金额':'Amount'} ${zh?'来源 / 层级':'From / Level'}
${zh?'状态':'Status'} ${zh?'时间':'Time'}
`; html += data.items.map(r => { const amt = Number(r.amount_usdt || 0).toFixed(2); // v2.x: 钱包 mask 跟 client maskWallet 同款 0x06e5****abcd 风格(中间 // **** 不是 ...,跟客户端 InviteView 统一,用户两边切换看到的视觉一致) const wallet = r.contributor_wallet ? r.contributor_wallet.slice(0,6) + '****' + r.contributor_wallet.slice(-4) : ''; // v2.x: 用户要求"list 给一个 tx_id"。tx_hash 长 66 chars,用 8 前 6 后 mask。 const txShort = r.tx_hash ? r.tx_hash.slice(0, 8) + '****' + r.tx_hash.slice(-6) : ''; const level = r.level ? 'L'+r.level : ''; const sent = r.status === 'sent'; // v2.x: 已发 chip 下方加 masked tx_hash;点 chip 仍然跳 bscscan const status = sent ? ` ✓ ${zh?'已发放':'paid'} ↗ ${txShort ? `${txShort}` : ''} ` : `⏳ ${zh?'待发':'pending'}`; return `
+${amt} USDT ${wallet} ${level}
${status} ${new Date(r.earned_at).toLocaleDateString()}
`; }).join(''); const total = data.total || 0; const totalPages = Math.max(1, Math.ceil(total / 10)); html += `
${_ucUsdtPage}/${totalPages}
`; sub.innerHTML = html; } // NOOB 奖励 — 三合一展示:邀请奖励 + 充值奖励 + 福袋。 // v2.x: 后端支持 ?reason=all 返回所有 reason,前端按 reason 给每行打徽章。 async function ucLoadRewardsNoob() { const zh = ucZh(); const data = await ucApi(`/api/user/referral/rewards?page=${_ucRewardPage}&pageSize=10&reason=all`); const sub = document.getElementById('uc-rewards-sub'); if (!data || !data.list || data.list.length === 0) { sub.innerHTML = emptyStateHtml('🪂', zh ? '暂无 NOOB 奖励记录' : 'No NOOB rewards yet', zh ? '好友充值给您发邀请奖励;您自己充值也有充值奖励;聊天可能掉福袋。' : 'Invite rewards from friends + top-up bonus on your own deposits + lucky bag drops.'); return; } // 来源徽章 helper — reason → { icon, label, color } const sourceBadge = (r) => { if (r.reason === 'referral_bonus') { return { icon: '🔗', label: (zh ? '邀请奖励' : 'Invite') + (r.level ? ` L${r.level}` : ''), color: 'bg-blue-500/15 text-blue-400' }; } if (r.reason === 'purchase_bonus') { return { icon: '💵', label: zh ? '充值奖励' : 'Top-up', color: 'bg-green-500/15 text-green-400' }; } if (r.reason === 'lucky_bag') { return { icon: '🎁', label: zh ? '福袋' : 'Lucky Bag', color: 'bg-yellow-500/15 text-yellow-400' }; } return { icon: '🪂', label: zh ? '空投' : 'Airdrop', color: 'bg-gray-500/15 text-gray-400' }; }; let html = `
${zh?'数量':'Amount'} ${zh?'来源':'Source'}
${zh?'时间':'Time'}
`; html += data.list.map(r => { const b = sourceBadge(r); // v2.x: '...' → '****' 跟 client maskWallet 风格统一(0x06e5****abcd) const wallet = r.contributorWallet ? r.contributorWallet.slice(0,6)+'****'+r.contributorWallet.slice(-4) : ''; return `
+${Number(r.noobAmount).toLocaleString()} NOOB ${b.icon}${b.label} ${wallet ? `${wallet}` : ''}
${new Date(r.createdAt).toLocaleDateString()}
`; }).join(''); const totalPages = Math.max(1, Math.ceil((data.total || 0) / 10)); html += `
${_ucRewardPage}/${totalPages}
`; sub.innerHTML = html; } // ─── Pending Order Modal ─── function ucShowPendingModal() { const zh = ucZh(); const overlay = document.createElement('div'); overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.7);z-index:9999;display:flex;align-items:center;justify-content:center;'; overlay.innerHTML = `

${zh ? '您有未完成的订单' : 'You have a pending order'}

${zh ? '请先完成支付,请在订单记录中查看' : 'Please complete payment. Check your order history.'}

`; document.body.appendChild(overlay); } // ─── Invite & Rebate (standalone page, works WITHOUT login) ─── // 公开入口的"邀请返佣"页。和 user-center 内的邀请区块功能/文案对齐, // 也跟 client InviteView 文案对齐(双重奖励:NoobCoin 空投 + USDT 真金返佣)。 // 未登录就展示 "--" 占位 + Connect Wallet CTA;登录后真实数据。所有 ID // 用 ir- 前缀避免和 user-center 的 uc- 冲突。 let _irInviteTab = 'records'; let _irInvitePage = 1; let _irRewardPage = 1; // v1.x: 「奖励明细」二级 tab,跟 uc 卡片 + client InviteView 对齐。 let _irRewardSubTab = 'usdt', _irUsdtPage = 1, _irCnyPage = 1; async function irInit() { const zh = ucZh(); const token = localStorage.getItem('noobclaw_token'); const wallet = localStorage.getItem('noobclaw_wallet'); const authed = !!(token && wallet); // ── 静态 i18n 标签(无论登录与否都填) ── document.getElementById('ir-page-title').textContent = zh ? '邀请返佣' : 'Invite & Rebate'; document.getElementById('ir-page-subtitle').textContent = zh ? '分享您的邀请链接,好友充值后,您将获得邀请奖励。' : 'Share your referral link. When a friend recharges, you earn referral rewards.'; document.getElementById('ir-unauth-title').textContent = zh ? '登录查看您的邀请数据' : 'Sign In to View Your Stats'; document.getElementById('ir-unauth-desc').textContent = cnIsCnSite() ? '使用社交账号登录后即可看到您的邀请链接、邀请人数和奖励收益。' : (zh ? '使用社交媒体账号或 Web3 钱包登录后即可看到您的邀请链接、邀请人数和返佣收益。' : 'Sign in with a social account or Web3 wallet to view your referral link, invitee count, and rebate earnings.'); document.getElementById('ir-unauth-btn').textContent = zh ? '登录' : 'Sign In'; document.getElementById('ir-lbl-invite').textContent = zh ? '邀请返佣' : 'Invite & Rebate'; // v1.x: 详细规则入口 — 中文/英语分别跳 docs.noobclaw.com 对应章节,新开 tab var _irRulesHref = zh ? 'https://docs.noobclaw.com/zhong-wen-ban/yao-qing-fan-yong-ji-zhi' : 'https://docs.noobclaw.com/english/affiliate-program'; var _irRulesText = zh ? '详细规则 →' : 'View Rules →'; var _irPageLink = document.getElementById('ir-page-rules-link'); if (_irPageLink) { _irPageLink.href = _irRulesHref; _irPageLink.textContent = _irRulesText; } document.getElementById('ir-lbl-mylink').textContent = zh ? '我的邀请链接' : 'My Referral Link'; document.getElementById('ir-copy-link-btn').textContent = zh ? '复制' : 'Copy'; document.getElementById('ir-lbl-bind').textContent = zh ? '绑定上级(邀请人)' : 'Bind Upper (Referrer)'; document.getElementById('ir-bind-btn').textContent = zh ? '绑定' : 'Bind'; document.getElementById('ir-bind-input').placeholder = zh ? '邀请人钱包地址 或 邀请链接' : 'Referrer wallet or link'; document.getElementById('ir-lbl-myreferrer').textContent = zh ? '我的邀请人' : 'My Referrer'; document.getElementById('ir-lbl-direct').textContent = zh ? '直接邀请' : 'Direct Referrals'; document.getElementById('ir-lbl-network').textContent = zh ? '全部网络' : 'Total Network'; // 我的CNY返佣 面板标签(原 ir-lbl-usdt 单卡已被面板取代,逐个 guard 防 null)。 { const e = document.getElementById('ir-lbl-cnypanel'); if (e) e.textContent = zh ? '💴 我的CNY返佣' : '💴 My CNY Rebate'; } { const e = document.getElementById('ir-lbl-earned'); if (e) e.textContent = zh ? '累计返佣' : 'Earned'; } { const e = document.getElementById('ir-lbl-withdrawable'); if (e) e.textContent = zh ? '可提现' : 'Withdrawable'; } { const e = document.getElementById('ir-lbl-paid'); if (e) e.textContent = zh ? '已提现' : 'Withdrawn'; } { const w = document.getElementById('ir-lbl-withdraw'); if (w) w.textContent = zh ? '立即提现' : 'Withdraw'; } document.getElementById('ir-tab-records').textContent = zh ? '邀请明细' : 'Records'; document.getElementById('ir-tab-rewards').textContent = zh ? '奖励明细' : 'Rewards'; document.getElementById('ir-lbl-hiw').textContent = zh ? '玩法说明' : 'How It Works'; document.getElementById('ir-hiw-1').textContent = zh ? '分享您的邀请链接' : 'Share your referral link'; document.getElementById('ir-hiw-1-desc').textContent = zh ? '发给微信、QQ、抖音、小红书 的朋友' : 'Send to friends on WeChat, QQ, Douyin, Xiaohongshu'; document.getElementById('ir-hiw-2').textContent = zh ? '好友通过链接注册并使用' : 'Friend signs up via your link'; document.getElementById('ir-hiw-2-desc').textContent = zh ? '邀请关系将被记录' : 'The referral relationship will be recorded'; document.getElementById('ir-hiw-3').innerHTML = zh ? '好友充值时,您将获得邀请奖励:' : 'When a friend recharges, you earn referral rewards:'; document.getElementById('ir-reward-usdt-title').textContent = zh ? '💰 邀请返佣' : '💰 Referral Rebate'; document.getElementById('ir-reward-usdt-desc').textContent = zh ? '好友通过您邀请链接充值后,系统会按邀请关系自动发放奖励到您账户,可在「奖励明细」中查看。' : 'When a friend recharges via your referral link, the system credits a reward to your account automatically. Check details in 「Rewards」.'; // ── 未登录:placeholder + 显著 Connect Wallet 横幅 ── if (!authed) { document.getElementById('ir-unauth-banner').classList.remove('hidden'); // 退出登录后若曾是合伙人,要把金色 banner 收起来 document.getElementById('ir-partner-hero').classList.add('hidden'); // v6.x: 同步收起非合伙人 2 列布局(我的钱包 + 申请卡) const _partnerRow = document.getElementById('ir-partner-row'); if (_partnerRow) _partnerRow.classList.add('hidden'); // 跑马灯也收起来 — 数据接口需要 auth,未登录拿不到 const _tk = document.getElementById('ir-ticker'); if (_tk) _tk.classList.add('hidden'); document.getElementById('ir-referral-link').textContent = '--'; document.getElementById('ir-copy-link-btn').disabled = true; document.getElementById('ir-copy-link-btn').classList.add('opacity-50', 'cursor-not-allowed'); document.getElementById('ir-bind-section').classList.add('hidden'); document.getElementById('ir-my-referrer').classList.add('hidden'); document.getElementById('ir-direct-count').textContent = '--'; document.getElementById('ir-network-count').textContent = '--'; document.getElementById('ir-usdt-total').textContent = '--'; document.getElementById('ir-tab-content').innerHTML = `

${zh ? '请先登录查看记录' : 'Sign in to view records'}

`; return; } // ── 已登录:隐藏 banner + 拉真数据 ── document.getElementById('ir-unauth-banner').classList.add('hidden'); document.getElementById('ir-copy-link-btn').disabled = false; document.getElementById('ir-copy-link-btn').classList.remove('opacity-50', 'cursor-not-allowed'); // cn 站邀请链接走 /cn/?ref= — 详见 ucInit 同款注释 document.getElementById('ir-referral-link').textContent = `https://noobclaw.com/cn/?ref=${wallet}`; const profile = await ucApi('/api/user/profile'); if (!profile) return; // ── Ticker (mirrors client InviteTicker.tsx) ── // Fetch up to 50 lines from /referral/ticker — backend mixes today's real // rebate_sends with day-seeded fakes so the strip is always populated. // Render the list TWICE in a row + translateX(-50%) for a seamless loop. try { const tk = await ucApi('/api/user/referral/ticker'); const tickerItems = (tk && tk.items) || []; const tickerWrap = document.getElementById('ir-ticker'); const tickerScroll = document.getElementById('ir-ticker-scroll'); if (tickerWrap && tickerScroll && tickerItems.length > 0) { const earnedLabel = zh ? '获得返佣' : 'earned'; const maskWallet = (a) => a && a.length >= 10 ? a.slice(0,6) + '****' + a.slice(-4) : (a || ''); const renderLine = (it, key) => '' + '💰' + '' + maskWallet(it.wallet) + '' + '' + earnedLabel + '' + (cnIsCnSite() ? '¥' + (Number(it.amount) * 7).toFixed(2) + '' : '' + Number(it.amount).toFixed(2) + ' USDT') + ''; // Render twice for seamless wrap-around let html = ''; for (let i = 0; i < tickerItems.length; i++) html += renderLine(tickerItems[i], '0-' + i); html += ''; for (let i = 0; i < tickerItems.length; i++) html += renderLine(tickerItems[i], '1-' + i); html += ''; tickerScroll.innerHTML = html; const durationSec = Math.max(30, Math.round(tickerItems.length * 1.2)); tickerScroll.style.animation = 'ir-ticker-scroll ' + durationSec + 's linear infinite'; tickerWrap.classList.remove('hidden'); } } catch (e) { /* non-fatal */ } // v2.x partner program — reveal 尊贵 banner if this wallet is an active partner. // Mirrors client InviteView PartnerHero render. Tier emoji from a small map; // multiplier vs default user computed on the fly for the side-comparison. const partnerHero = document.getElementById('ir-partner-hero'); if (profile.partner && profile.partner.is_partner) { const p = profile.partner; // 完整 tier 主题 — bg 渐变 / shimmer 颜色 / 主色都跟着等级换。 // 跟 client PartnerHero.tsx TIER_VISUAL 保持一致。 // v2.x:tier 主色重做,Diamond/Platinum、Gold/Bronze 拉开视觉差异 const tierMap = { bronze: { emoji: '🥉', label: 'Bronze', color: '#c46e2a', bgGrad: 'linear-gradient(135deg, #1f0e04 0%, #3a1d08 50%, #1f0e04 100%)', shimmer: 'rgba(196, 110, 42, 0.20)', }, gold: { emoji: '👑', label: 'Gold', color: '#fbbf24', bgGrad: 'linear-gradient(135deg, #1f1306 0%, #3a2607 50%, #1f1306 100%)', shimmer: 'rgba(251, 191, 36, 0.20)', }, platinum: { // v3.x: 旧 'silver' enum 已 rename 成 'platinum'(DB + 代码统一, // 跟 PARTNER_TIER_VISUAL + partnerTier.ts 同步)。 emoji: '🏆', label: 'Platinum', color: '#dde4ef', bgGrad: 'linear-gradient(135deg, #0c1220 0%, #1e2840 50%, #0c1220 100%)', shimmer: 'rgba(221, 228, 239, 0.30)', }, diamond: { emoji: '💎', label: 'Diamond', color: '#22d3ee', bgGrad: 'linear-gradient(135deg, #061a20 0%, #0b3340 50%, #061a20 100%)', shimmer: 'rgba(34, 211, 238, 0.24)', }, }; const visual = (p.tier && tierMap[p.tier]) || tierMap.gold; document.getElementById('ir-partner-emoji').textContent = visual.emoji; document.getElementById('ir-partner-tier').textContent = visual.label; document.getElementById('ir-partner-title').textContent = zh ? '尊享合伙人' : 'Partner'; // 显示 rate_pct(admin 设的总池),不是派生的 L1 个人份额。 // admin 设 30 → 用户看 30,跟 admin 心智模型一致;50/10 内部切分是实现细节。 document.getElementById('ir-partner-l1-label').textContent = zh ? '返佣比例' : 'Rebate Rate'; animateCount(document.getElementById('ir-partner-rate'), profitSharePct(p.rate_pct), { suffix: '%' }); // "按充值金额" 替代了之前的 "vs 普通用户 10% · 3.0x" — 简洁,只说计费单位 document.getElementById('ir-partner-compare').textContent = zh ? '(按平台净利润)' : '(of platform net profit)'; // Override 真金返佣 rules text with partner's actual rate (was 10%). // 普通用户 see the original 10% line set earlier in irInit; partners // see their boosted rate so the "10%" doesn't lie when they're earning 30%. const _irDescEl = document.getElementById('ir-reward-usdt-desc'); if (_irDescEl) { // cn 站含蓄版,主站走原文案 _irDescEl.textContent = cnIsCnSite() ? '您是合伙人,享更高比例返佣。好友通过您邀请链接充值后,系统会按邀请关系自动发放奖励到您账户。' : (zh ? '好友每笔充值产生的平台净利润,其中 ' + profitSharePct(p.rate_pct) + '% 作为您的返佣,按 6 层邀请链路分配。佣金 5 分钟内以 BNB Chain 上的 USDT 形式实时自动发放到您钱包。' : 'Every friend top-up generates platform net profit — ' + profitSharePct(p.rate_pct) + '% of it becomes your rebate, distributed across your 6-level invite chain. Auto-paid in real-time (within 5 min) as USDT on BNB Chain.'); } // Apply FULL theme — background gradient + shimmer color + every text // accent color. Each tier has its own coordinated palette so silver // 看着是冷银,bronze 是暖铜,gold 暖金,diamond 冰蓝。 partnerHero.style.background = visual.bgGrad; partnerHero.style.borderColor = visual.color + '60'; partnerHero.style.boxShadow = '0 0 24px ' + visual.color + '25, inset 0 0 14px ' + visual.color + '10'; // Update shimmer band color (second child of partnerHero is the absolute-positioned shimmer div) const shimmer = partnerHero.querySelector('.ir-partner-shimmer'); if (shimmer) { shimmer.style.background = 'linear-gradient(90deg, transparent 0%, ' + visual.shimmer + ' 50%, transparent 100%)'; } document.getElementById('ir-partner-title').style.color = visual.color; document.getElementById('ir-partner-l1-label').style.color = visual.color + 'cc'; // 数字用 tier 三色渐变(浅→主色→深),background-clip:text 实现金属字效。 // 三色用 visual.color 做基准,外推浅色/深色得到 lighter / darker。 const lighten = (hex) => '#' + hex.slice(1).match(/.{2}/g).map(c => Math.min(255, parseInt(c, 16) + 60).toString(16).padStart(2,'0')).join(''); const darken = (hex) => '#' + hex.slice(1).match(/.{2}/g).map(c => Math.max(0, parseInt(c, 16) - 60).toString(16).padStart(2,'0')).join(''); const rateEl = document.getElementById('ir-partner-rate'); rateEl.style.background = 'linear-gradient(135deg,' + lighten(visual.color) + ' 0%,' + visual.color + ' 50%,' + darken(visual.color) + ' 100%)'; rateEl.style.webkitBackgroundClip = 'text'; rateEl.style.backgroundClip = 'text'; rateEl.style.webkitTextFillColor = 'transparent'; rateEl.style.filter = 'drop-shadow(0 0 8px ' + visual.color + '40)'; document.getElementById('ir-partner-compare').style.color = visual.color + 'cc'; // 粒子 + emoji 阴影 + conic 边框颜色都跟着 tier 走 partnerHero.querySelectorAll('.ir-partner-spark').forEach(s => { s.style.background = 'radial-gradient(circle,' + visual.color + ' 0%, transparent 70%)'; }); const emojiEl = document.getElementById('ir-partner-emoji'); if (emojiEl) emojiEl.style.filter = 'drop-shadow(0 0 8px ' + visual.color + '60)'; const conicEl = partnerHero.querySelector('.ir-partner-conic'); if (conicEl) { conicEl.style.background = 'conic-gradient(from 0deg, transparent 0%,' + visual.color + ' 20%, transparent 40%, transparent 60%,' + visual.color + ' 80%, transparent 100%)'; } const vipEl = partnerHero.querySelector('.ir-partner-vip'); if (vipEl) { vipEl.style.background = 'linear-gradient(135deg,' + visual.color + ',' + darken(visual.color) + ')'; vipEl.style.boxShadow = '0 0 8px ' + visual.color + '80'; } partnerHero.classList.remove('hidden'); // ────── 整页 tier 主题化 ────── // 邀请返佣卡片整体也染上 tier 色调,而不是只染 hero banner。 // 包括:卡片边框、统计数字、复制按钮、详细规则链接、tab 选中色、邀请链接颜色。 // 用 CSS 变量 + body data-tier 属性 + 一段