狐蒂云自动抢购脚本

使用浏览器插件Tampermonkey

自行下载并安装浏览器插件,新建脚本,然后执行即可

注意:要设置执行权限

// ==UserScript==
  // @name         狐蒂云自动抢购(购物车提交后暂停+侧栏缩放)
  // @namespace    http://tampermonkey.net/
  // @version      0.9.2
  // @description  进入支付页或购物车提交后暂停,支持缩放到侧栏,含抢购时间提示
  // @match        https://www.szhdy.com/*
  // @grant        none
  // ==/UserScript==

  (function () {
    'use strict';

    /** ==========================
     * ⚙️ 默认配置
     * =========================== */
    const defaultConfig = {
      startTime: "2025-10-18 08:00:00",
      endTime: "2025-10-25 13:00:00",
      productIds: ["317", "345", "336"],
      checkInterval: 500,
      minRandomInterval: 450,
      maxRandomInterval: 550,
      refreshAfterFails: 5,
      loopUntilSuccess: true,
      sidebarMode: false
    };

    /** ==========================
     * 💾 配置处理
     * =========================== */
    const loadConfig = () => {
      try {
        const saved = JSON.parse(localStorage.getItem("hudiyun_config"));
        return saved ? { ...defaultConfig, ...saved } : defaultConfig;
      } catch {
        return defaultConfig;
      }
    };

    const saveConfig = (cfg) => {
      localStorage.setItem("hudiyun_config", JSON.stringify(cfg));
    };

    // 时间格式转换工具
    const toDateTimeLocalFormat = (timeStr) => {
      return timeStr.replace(' ', 'T').slice(0, 16);
    };

    const fromDateTimeLocalFormat = (dtStr) => {
      return dtStr.replace('T', ' ') + ':00';
    };

    const config = loadConfig();
    let failCount = 0;

    /** ==========================
     * 🧠 工具函数 + 页面判断
     * =========================== */
    const isProtectedPage = () => {
      const url = location.href;
      return url.includes("action=configureproduct")
          || url.includes("action=viewcart")
          || url.includes("payment")
          || url.includes("pay");
    };

    const isPaymentPage = () => {
      const url = location.href;
      return url.includes("payment") || url.includes("pay");
    };

    const isCartPage = () => {
      return location.href.includes("action=viewcart");
    };

    const sleep = (ms = null) => {
      const delay = ms || Math.floor(Math.random() * (config.maxRandomInterval - config.minRandomInterval + 1)) + config.minRandomInterval;
      return new Promise((r) => setTimeout(r, delay));
    };

    const now = () => new Date().getTime();
    const formatTime = (ts) => new Date(ts).toTimeString().split(" ")[0];
    const playSound = () => {
      try {
        const audio = new Audio("https://assets.mixkit.co/sfx/preview/mixkit-achievement-bell-600.mp3");
        audio.preload = "auto";
        audio.play().catch(() => console.warn("[狐蒂云] 请点击页面启用声音"));
      } catch (e) {
        console.error("[狐蒂云] 播放失败", e);
      }
    };

    playSound();

    const showNotify = (t, s = false) => {
      alert(`🎉 ${t}`);
      console.log(`[狐蒂云] ${t}`);
      if (s) playSound();
    };

    const waitFor = async (sel, t = isProtectedPage() ? 800 : 500) => {
      const s = Date.now();
      while (Date.now() - s < t) {
        const el = document.querySelector(sel);
        if (el) return el;
        await sleep(100);
      }
      return null;
    };

    /** ==========================
     * 🧠 控制面板(新增抢购时间提示)
     * =========================== */
    let isRunning = true;
    const createPanel = () => {
      // 样式新增提示文字样式
      const style = document.createElement('style');
      style.textContent = `
        #hud-panel {
          font-family: system-ui, sans-serif;
          position: fixed;
          right: 0;
          bottom: 0;
          width: 300px;
          z-index: 99999;
          transition: width 0.3s ease;
        }
        #hud-panel.sidebar {
          width: 180px;
        }
        .hud-card {
          background: #1a1a1a;
          border-radius: 8px 0 0 8px;
          box-shadow: 0 2px 10px rgba(0,0,0,0.3);
          color: #f0f0f0;
          overflow: hidden;
        }
        .hud-header {
          background: #333;
          padding: 8px 12px;
          font-weight: 500;
          font-size: 14px;
          display: flex;
          justify-content: space-between;
          align-items: center;
        }
        .scale-btn {
          cursor: pointer;
          font-size: 16px;
          padding: 0 4px;
        }
        .protected-tag, .payment-tag, .cart-tag {
          font-size: 10px;
          padding: 1px 4px;
          border-radius: 2px;
        }
        .protected-tag { background: #4cd964; color: #000; }
        .payment-tag { background: #ff9500; color: #000; }
        .cart-tag { background: #5856d6; color: white; }
        .hud-status, .hud-config {
          padding: 10px 12px;
          font-size: 12px;
        }
        .hud-status {
          border-bottom: 1px solid #333;
        }
        .status-item {
          margin: 4px 0;
          display: flex;
          justify-content: space-between;
        }
        .status-label { color: #aaa; }
        .status-running { color: #4cd964; }
        .status-paused { color: #ffcc00; }
        .status-ending { color: #ff3b30; }
        .status-protected { color: #00ccff; }
        /* 新增:抢购时间提示样式 */
        .rush-time-hint {
          color: #4cd964; /* 绿色提示色 */
          font-size: 11px;
          padding: 5px 0 8px;
          border-bottom: 1px dashed #444;
          margin-bottom: 8px;
        }
        .config-group {
          margin-bottom: 8px;
        }
        .config-label {
          display: block;
          color: #aaa;
          margin-bottom: 3px;
          font-size: 11px;
        }
        .config-input {
          width: 100%;
          padding: 5px 8px;
          background: #2a2a2a;
          border: 1px solid #444;
          border-radius: 4px;
          color: #f0f0f0;
          font-size: 12px;
          box-sizing: border-box;
        }
        .config-input:focus {
          outline: none;
          border-color: #4cd964;
        }
        input[type="datetime-local"] {
          color-scheme: dark;
          font-size: 11px;
        }
        .hud-actions {
          display: flex;
          padding: 8px 12px;
          gap: 5px;
          background: #222;
        }
        .hud-btn {
          flex: 1;
          padding: 5px 0;
          border: none;
          border-radius: 4px;
          font-size: 12px;
          cursor: pointer;
        }
        .hud-btn.toggle { background: #4cd964; color: #000; }
        .hud-btn.save { background: #ffcc00; color: #000; }
        .hud-btn.refresh {
          background: #ff3b30;
          color: white;
          opacity: var(--refresh-opacity, 1);
          pointer-events: var(--refresh-events, auto);
        }
        .hud-btn:active { opacity: 0.8; }
        /* 侧栏模式隐藏配置区(含提示文字)和操作区 */
        #hud-panel.sidebar .hud-config,
        #hud-panel.sidebar .hud-actions {
          display: none;
        }
      `;
      document.head.appendChild(style);

      const p = document.createElement("div");
      p.id = "hud-panel";
      if (config.sidebarMode) p.classList.add("sidebar");

      const isProtected = isProtectedPage();
      const isPayment = isPaymentPage();
      const isCart = isCartPage();

      if (isPayment) {
        isRunning = false;
      }

      p.innerHTML = `
        <div class="hud-card">
          <div class="hud-header">
            狐蒂云自动抢购
            <span class="scale-btn" id="scale-btn">${config.sidebarMode ? '→' : '←'}</span>
            ${isPayment ? '<span class="payment-tag">支付页</span>' :
              isCart ? '<span class="cart-tag">购物车</span>' :
              (isProtected ? '<span class="protected-tag">保护页</span>' : '')}
          </div>

          <div class="hud-status">
            <div class="status-item">
              <span class="status-label">状态:</span>
              <span id="hud-status" class="${isPayment ? 'status-paused' :
                isCart ? (isRunning ? 'status-protected' : 'status-paused') :
                (isProtected ? 'status-protected' : 'status-running')}">
                ${isPayment ? '已暂停(支付页)' :
                  isCart ? (isRunning ? '购物车(运行中)' : '已暂停(已提交)') :
                  (isProtected ? '保护页(不刷新)' : '运行中')}
              </span>
            </div>
            <div class="status-item">
              <span class="status-label">时间:</span>
              <span id="hud-time"></span>
            </div>
            <div class="status-item">
              <span class="status-label">剩余:</span>
              <span id="hud-countdown"></span>
            </div>
            <div class="status-item">
              <span class="status-label">检测:</span>
              <span id="hud-check"></span>
            </div>
          </div>

          <!-- 配置区:新增抢购时间提示(侧栏模式隐藏) -->
          <div class="hud-config">
            <!-- 新增内容:抢购时间提示 -->
            <div class="rush-time-hint">
              全天监控模式已开启
            </div>

            <div class="config-group">
              <label class="config-label">开始时间</label>
              <input id="cfg-start" type="datetime-local" value="${toDateTimeLocalFormat(config.startTime)}" class="config-input">
            </div>
            <div class="config-group">
              <label class="config-label">结束时间</label>
              <input id="cfg-end" type="datetime-local" value="${toDateTimeLocalFormat(config.endTime)}" class="config-input">
            </div>
            <div class="config-group">
              <label class="config-label">商品ID (逗号分隔)</label>
              <input id="cfg-pid" type="text" value="${config.productIds.join(',')}" class="config-input">
            </div>
            <div style="display: flex; gap: 8px;">
              <div class="config-group" style="flex: 1;">
                <label class="config-label">检查间隔(ms)</label>
                <input id="cfg-interval" type="number" value="${config.checkInterval}" class="config-input">
              </div>
              <div class="config-group" style="flex: 1;">
                <label class="config-label">刷新阈值(次)</label>
                <input id="cfg-refresh" type="number" value="${config.refreshAfterFails}" class="config-input">
              </div>
            </div>
          </div>

          <div class="hud-actions">
            <button id="hud-toggle" class="hud-btn toggle">
              ${isRunning ? '暂停' : '开始'}
            </button>
            <button id="hud-save" class="hud-btn save">保存</button>
            <button id="hud-refresh" class="hud-btn refresh">刷新</button>
          </div>
        </div>
      `;
      document.body.appendChild(p);

      if (isProtected) {
        const refreshBtn = document.querySelector("#hud-refresh");
        refreshBtn.style.setProperty('--refresh-opacity', '0.5');
        refreshBtn.style.setProperty('--refresh-events', 'none');
      }

      // 缩放按钮事件
      const scaleBtn = document.querySelector("#scale-btn");
      scaleBtn.addEventListener("click", () => {
        const panel = document.querySelector("#hud-panel");
        config.sidebarMode = !config.sidebarMode;
        if (config.sidebarMode) {
          panel.classList.add("sidebar");
          scaleBtn.textContent = '→';
        } else {
          panel.classList.remove("sidebar");
          scaleBtn.textContent = '←';
        }
        saveConfig(config);
      });

      // 原有按钮事件
      document.querySelector("#hud-toggle").addEventListener("click", () => {
        isRunning = !isRunning;
        const btn = document.querySelector("#hud-toggle");
        const statusEl = document.querySelector("#hud-status");
        const isProtected = isProtectedPage();
        const isPayment = isPaymentPage();
        const isCart = isCartPage();

        btn.textContent = isRunning ? "暂停" : "开始";
        if (isRunning) {
          btn.className = "hud-btn toggle";
          if (isPayment) {
            statusEl.className = "status-paused";
            statusEl.textContent = "已暂停(支付页)";
          } else if (isCart) {
            statusEl.className = "status-protected";
            statusEl.textContent = "购物车(运行中)";
          } else {
            statusEl.className = isProtected ? "status-protected" : "status-running";
            statusEl.textContent = isProtected ? "保护页(不刷新)" : "运行中";
          }
        } else {
          btn.className = "hud-btn toggle status-paused";
          statusEl.className = "status-paused";
          statusEl.textContent = isPayment ? "已暂停(支付页)" : isCart ? "已暂停(已提交)" : "已暂停";
        }
      });

      document.querySelector("#hud-save").addEventListener("click", () => {
        config.startTime = fromDateTimeLocalFormat(document.querySelector("#cfg-start").value);
        config.endTime = fromDateTimeLocalFormat(document.querySelector("#cfg-end").value);
        config.productIds = document.querySelector("#cfg-pid").value.split(",").map(x => x.trim());
        config.checkInterval = parseInt(document.querySelector("#cfg-interval").value) || 500;
        config.refreshAfterFails = parseInt(document.querySelector("#cfg-refresh").value) || 500000000;
        saveConfig(config);

        const saveBtn = document.querySelector("#hud-save");
        const originalText = saveBtn.textContent;
        saveBtn.textContent = "已保存";
        setTimeout(() => saveBtn.textContent = originalText, 1000);
      });

      document.querySelector("#hud-refresh").addEventListener("click", () => {
        if (isProtectedPage()) return;
        document.querySelector("#hud-check").textContent = "正在刷新...";
        setTimeout(() => location.reload(), 500);
      });
    };

    /** ==========================
     * 🧠 面板更新
     * =========================== */
    const updatePanel = (status, info = "") => {
      const nowTime = formatTime(Date.now());
      const endMs = new Date(config.endTime.replace(/-/g, "/")).getTime();
      const left = Math.max(0, ((endMs - now()) / 1000).toFixed(0));
      const statusEl = document.querySelector("#hud-status");
      const isProtected = isProtectedPage();
      const isPayment = isPaymentPage();
      const isCart = isCartPage();

      if (isPayment) {
        statusEl.className = "status-paused";
        statusEl.textContent = "已暂停(支付页)";
        document.querySelector("#hud-check").textContent = "已暂停操作";
      } else if (isCart) {
        statusEl.className = isRunning ? "status-protected" : "status-paused";
        statusEl.textContent = isRunning ? "购物车(运行中)" : "已暂停(已提交)";
        document.querySelector("#hud-check").textContent = `[购物车] ${info}`;
      } else if (isProtected) {
        statusEl.className = "status-protected";
        statusEl.textContent = "保护页(不刷新)";
        document.querySelector("#hud-check").textContent = `[保护页] ${info}`;
      } else {
        statusEl.className = status.includes("结束") ? "status-ending"
          : status.includes("暂停") ? "status-paused"
          : "status-running";
        statusEl.textContent = status;
        document.querySelector("#hud-check").textContent = `${info} (${failCount}/${config.refreshAfterFails})`;
      }

      document.querySelector("#hud-time").textContent = nowTime;
      document.querySelector("#hud-countdown").textContent = `${left}s`;
    };

    /** ==========================
     * 🦊 核心逻辑
     * =========================== */
    const waitUntilTimeRange = async () => {
      const start = new Date(config.startTime.replace(/-/g, "/")).getTime();
      updatePanel("等待中", `开始于 ${formatTime(start)}`);
      while (now() < start) {
        if (!isRunning) return;
        const left = ((start - now()) / 1000).toFixed(1);
        updatePanel("等待中", `剩余 ${left}s`);
        await sleep(500);
      }
      updatePanel("抢购中", "检测商品...");
    };

    const restartIfNeeded = () => {
      if (isProtectedPage()) {
        updatePanel("保护页", "加载失败");
        return;
      }

      if (config.loopUntilSuccess) {
        updatePanel("重试中", "刷新页面...");
        setTimeout(() => location.reload(), config.checkInterval);
      }
    };

    const autoRefreshIfNeeded = () => {
      if (isProtectedPage()) return true;

      failCount++;
      if (failCount >= config.refreshAfterFails) {
        updatePanel("刷新中", `连续${failCount}次未发现`);
        setTimeout(() => location.reload(), 500);
        return true;
      }
      return false;
    };

    const tryBuyProduct = async () => {
      const productElements = document.querySelectorAll('[data-id]');
      for (const pid of config.productIds) {
        let product = null;
        for (let el of productElements) {
          if (el.getAttribute('data-id') === pid) {
            product = el;
            break;
          }
        }

        if (!product) continue;

        const button = product.querySelector(".form-footer-butt");
        if (!button) continue;

        const txt = button.textContent.trim();
        if (txt.includes("售罄") || txt.includes("结束")) {
          updatePanel("抢购中", `ID=${pid} 售罄`);
          continue;
        }

        failCount = 0;
        updatePanel("抢购中", `点击购买 ID=${pid}`);
        button.dispatchEvent(new MouseEvent('click', {
          bubbles: true,
          cancelable: true,
          view: window
        }));
        return true;
      }
      return false;
    };

    const doIt = async () => {
      createPanel();

      if (isPaymentPage()) {
        updatePanel("", "已暂停操作");
        return;
      }

      await waitUntilTimeRange();
      const end = new Date(config.endTime.replace(/-/g, "/")).getTime();
      const url = location.href;

      const runLoop = async () => {
    if (isPaymentPage()) {
      isRunning = false;
      updatePanel("", "已暂停操作");
      document.querySelector("#hud-toggle").textContent = "开始";
      document.querySelector("#hud-toggle").className = "hud-btn toggle status-paused";
      return;
    }

    if (!isRunning) {
      updatePanel("已暂停", "等待恢复");
      setTimeout(runLoop, 500);
      return;
    }

    const end = new Date(config.endTime.replace(/-/g, "/")).getTime();
    if (now() > end) {
      updatePanel("已结束", "时间到");
      return;
    }

    // 打印当前时间和状态
    const currentTime = new Date().toLocaleTimeString();
    console.log(`[${currentTime}] 当前状态: ${isRunning ? "运行中" : "已暂停"}`);

    if (url.includes("activities/default.html?method=activity")) {
      const success = await tryBuyProduct();
      if (success) {
        await sleep(1000);
      } else {
        const refreshed = autoRefreshIfNeeded();
        if (!refreshed) {
          updatePanel("抢购中", `未发现商品`);
        } else {
          return;
        }
      }
    } else if (url.includes("action=configureproduct")) {
      failCount = 0;
      updatePanel("保护页", "尝试加入购物车");
      const btn = await waitFor(".btn-buyNow");
      if (btn) {
        btn.click();
        await sleep(1500);
      } else {
        restartIfNeeded();
      }
    } else if (url.includes("action=viewcart")) {
      failCount = 0;
      updatePanel("购物车", "准备提交订单");

      const nextStep = await waitFor(".nextStep");
      if (nextStep) {
        nextStep.click();
        await sleep(800);
      }

      const pay = document.querySelector(".payment-checkbox");
      const sure = document.querySelector(".sky-viewcart-terms-checkbox");
      if (pay) pay.checked = true;
      if (sure) sure.checked = true;

      const submit = await waitFor(".submit-btn");
      if (submit) {
        submit.click();
        updatePanel("购物车", "订单已提交,自动暂停");
        isRunning = false;
        document.querySelector("#hud-toggle").textContent = "开始";
        document.querySelector("#hud-toggle").className = "hud-btn toggle status-paused";
        return;
      } else {
        restartIfNeeded();
      }
    } else {
      failCount = 0;
      updatePanel("空闲", "等待检测");
    }

    setTimeout(runLoop, config.checkInterval);
  };


      runLoop();
    };

    if (document.readyState === "complete") {
      doIt();
    } else {
      window.addEventListener("load", doIt);
    }
  })();
请登录后发表评论

    没有回复内容