首页 / 应用软件 / 开发指南,打造网站内嵌的在线抽奖与幸运大转盘互动营销组件

开发指南,打造网站内嵌的在线抽奖与幸运大转盘互动营销组件

开发指南:打造网站内嵌的在线抽奖与幸运大转盘互动营销组件

摘要

在当今数字营销时代,互动式营销工具已成为提升用户参与度和转化率的关键手段。本文将详细介绍如何通过WordPress程序的代码二次开发,实现一个功能完整的在线抽奖与幸运大转盘互动营销组件。我们将从需求分析、技术选型、代码实现到部署测试,全面解析开发流程,帮助开发者快速构建这一常用互联网小工具功能。


目录

  1. 引言:互动营销组件的重要性
  2. 需求分析与功能规划
  3. 技术架构与开发环境搭建
  4. 数据库设计与数据模型
  5. 前端实现:转盘界面与交互设计
  6. 后端开发:抽奖逻辑与数据管理
  7. WordPress集成与插件化开发
  8. 安全性与性能优化
  9. 测试与部署策略
  10. 维护与扩展建议
  11. 结语:未来发展方向

1. 引言:互动营销组件的重要性

在竞争激烈的互联网环境中,网站需要不断创新以吸引和留住用户。互动营销组件,如在线抽奖和幸运大转盘,已成为提升用户参与度、增加页面停留时间、促进转化的有效工具。这些组件不仅能够增强用户体验,还能为网站运营者提供宝贵的用户行为数据。

WordPress作为全球最流行的内容管理系统,拥有庞大的用户基础和丰富的扩展生态。通过二次开发,我们可以将定制化的互动营销组件无缝集成到WordPress网站中,满足特定业务需求,同时保持与现有主题和插件的兼容性。

2. 需求分析与功能规划

2.1 核心功能需求

  1. 转盘可视化界面:美观、可自定义的转盘界面,支持多种奖品设置
  2. 抽奖逻辑系统:可配置的中奖概率、奖品库存管理
  3. 用户参与管理:用户身份验证、参与次数限制、中奖记录
  4. 数据统计与分析:参与数据、中奖率、用户行为分析
  5. 后台管理界面:奖品管理、概率设置、数据监控

2.2 非功能性需求

  1. 响应式设计:适配各种设备屏幕尺寸
  2. 性能优化:快速加载和流畅的动画效果
  3. 安全性:防止作弊和恶意攻击
  4. 可扩展性:便于未来功能扩展和定制

2.3 用户角色与权限

  • 网站管理员:完全控制抽奖设置和数据管理
  • 编辑人员:管理奖品内容和基本设置
  • 普通用户:参与抽奖活动,查看中奖记录
  • 未注册访客:有限次数的参与机会

3. 技术架构与开发环境搭建

3.1 技术选型

  • 前端技术:HTML5、CSS3、JavaScript (ES6+)、Canvas/SVG(转盘绘制)
  • 动画库:GSAP或CSS3动画实现流畅转盘效果
  • 后端技术:PHP 7.4+(WordPress核心语言)
  • 数据库:MySQL(WordPress默认数据库)
  • WordPress开发:遵循WordPress插件开发规范

3.2 开发环境配置

  1. 本地开发环境:安装XAMPP/MAMP或Local by Flywheel
  2. WordPress安装:最新稳定版WordPress
  3. 代码编辑器:VS Code或PHPStorm
  4. 版本控制:Git
  5. 调试工具:浏览器开发者工具、Xdebug

3.3 项目结构规划

wp-content/plugins/lucky-wheel-roulette/
├── assets/
│   ├── css/
│   ├── js/
│   └── images/
├── includes/
│   ├── class-database.php
│   ├── class-wheel-ui.php
│   ├── class-lottery-logic.php
│   └── class-admin-panel.php
├── templates/
│   ├── frontend-wheel.php
│   └── admin-settings.php
├── languages/
├── lucky-wheel-roulette.php (主插件文件)
└── uninstall.php

4. 数据库设计与数据模型

4.1 自定义数据表设计

除了使用WordPress默认的数据表,我们需要创建几个自定义表来存储抽奖相关数据:

-- 奖品表
CREATE TABLE wp_lwr_prizes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    image_url VARCHAR(500),
    probability DECIMAL(5,4) DEFAULT 0.1,
    stock INT DEFAULT 0,
    daily_limit INT DEFAULT 0,
    type ENUM('physical', 'virtual', 'coupon') DEFAULT 'virtual',
    value VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 抽奖记录表
CREATE TABLE wp_lwr_records (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id BIGINT(20) UNSIGNED,
    prize_id INT,
    ip_address VARCHAR(45),
    user_agent TEXT,
    result ENUM('win', 'lose') DEFAULT 'lose',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES wp_users(ID) ON DELETE SET NULL,
    FOREIGN KEY (prize_id) REFERENCES wp_lwr_prizes(id) ON DELETE SET NULL
);

-- 用户抽奖次数表
CREATE TABLE wp_lwr_user_attempts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id BIGINT(20) UNSIGNED,
    attempts_today INT DEFAULT 0,
    total_attempts INT DEFAULT 0,
    last_attempt_date DATE,
    FOREIGN KEY (user_id) REFERENCES wp_users(ID) ON DELETE CASCADE
);

4.2 数据模型类实现

// includes/class-database.php
class LWR_Database {
    private static $instance = null;
    private $wpdb;
    private $table_prizes;
    private $table_records;
    private $table_user_attempts;
    
    private function __construct() {
        global $wpdb;
        $this->wpdb = $wpdb;
        $this->table_prizes = $wpdb->prefix . 'lwr_prizes';
        $this->table_records = $wpdb->prefix . 'lwr_records';
        $this->table_user_attempts = $wpdb->prefix . 'lwr_user_attempts';
    }
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    // 创建数据表
    public function create_tables() {
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        
        $charset_collate = $this->wpdb->get_charset_collate();
        
        // 创建奖品表
        $sql_prizes = "CREATE TABLE IF NOT EXISTS {$this->table_prizes} (
            id INT AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(255) NOT NULL,
            description TEXT,
            image_url VARCHAR(500),
            probability DECIMAL(5,4) DEFAULT 0.1,
            stock INT DEFAULT 0,
            daily_limit INT DEFAULT 0,
            type ENUM('physical', 'virtual', 'coupon') DEFAULT 'virtual',
            value VARCHAR(255),
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        ) {$charset_collate};";
        
        dbDelta($sql_prizes);
        
        // 创建其他表的SQL语句...
        
        // 插入默认奖品数据
        $this->insert_default_prizes();
    }
    
    // 插入默认奖品
    private function insert_default_prizes() {
        $default_prizes = array(
            array('name' => '一等奖', 'probability' => 0.01, 'type' => 'virtual'),
            array('name' => '二等奖', 'probability' => 0.05, 'type' => 'virtual'),
            array('name' => '三等奖', 'probability' => 0.1, 'type' => 'virtual'),
            array('name' => '谢谢参与', 'probability' => 0.84, 'type' => 'virtual')
        );
        
        foreach ($default_prizes as $prize) {
            $this->wpdb->insert(
                $this->table_prizes,
                $prize
            );
        }
    }
    
    // 获取所有奖品
    public function get_prizes() {
        return $this->wpdb->get_results(
            "SELECT * FROM {$this->table_prizes} ORDER BY probability ASC"
        );
    }
    
    // 保存抽奖记录
    public function save_record($user_id, $prize_id, $ip, $user_agent, $result) {
        return $this->wpdb->insert(
            $this->table_records,
            array(
                'user_id' => $user_id,
                'prize_id' => $prize_id,
                'ip_address' => $ip,
                'user_agent' => $user_agent,
                'result' => $result
            )
        );
    }
    
    // 其他数据库操作方法...
}

5. 前端实现:转盘界面与交互设计

5.1 HTML结构

<!-- templates/frontend-wheel.php -->
<div id="lucky-wheel-container" class="lwr-container">
    <div class="lwr-wheel-wrapper">
        <canvas id="lucky-wheel-canvas" width="500" height="500"></canvas>
        <div class="lwr-wheel-pointer">
            <div class="pointer-arrow"></div>
        </div>
        <button id="spin-button" class="lwr-spin-button">开始抽奖</button>
    </div>
    
    <div class="lwr-sidebar">
        <div class="lwr-prize-list">
            <h3>奖品列表</h3>
            <ul id="prize-list">
                <!-- 通过JavaScript动态加载 -->
            </ul>
        </div>
        
        <div class="lwr-user-info">
            <h3>我的信息</h3>
            <p>今日剩余次数: <span id="remaining-attempts">3</span></p>
            <p>总参与次数: <span id="total-attempts">0</span></p>
        </div>
        
        <div class="lwr-winning-history">
            <h3>中奖记录</h3>
            <ul id="winning-history">
                <!-- 通过JavaScript动态加载 -->
            </ul>
        </div>
    </div>
    
    <!-- 中奖结果弹窗 -->
    <div id="result-modal" class="lwr-modal">
        <div class="lwr-modal-content">
            <span class="lwr-close-modal">&times;</span>
            <h2 id="result-title">恭喜中奖!</h2>
            <div id="result-details">
                <!-- 中奖详情 -->
            </div>
            <button id="claim-prize" class="lwr-claim-button">领取奖品</button>
        </div>
    </div>
</div>

5.2 CSS样式设计

/* assets/css/lucky-wheel.css */
.lwr-container {
    display: flex;
    flex-wrap: wrap;
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
    font-family: 'Arial', sans-serif;
}

.lwr-wheel-wrapper {
    position: relative;
    flex: 1;
    min-width: 300px;
    max-width: 500px;
    margin: 0 auto 30px;
}

#lucky-wheel-canvas {
    width: 100%;
    height: auto;
    border-radius: 50%;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
    transition: transform 0.1s;
}

.lwr-wheel-pointer {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 60px;
    height: 60px;
    z-index: 10;
}

.pointer-arrow {
    width: 0;
    height: 0;
    border-left: 30px solid transparent;
    border-right: 30px solid transparent;
    border-top: 50px solid #e74c3c;
    position: absolute;
    top: -40px;
    left: 0;
}

.lwr-spin-button {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background: linear-gradient(145deg, #e74c3c, #c0392b);
    color: white;
    border: none;
    font-size: 18px;
    font-weight: bold;
    cursor: pointer;
    z-index: 5;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
    transition: all 0.3s;
}

.lwr-spin-button:hover {
    transform: translate(-50%, -50%) scale(1.05);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
}

.lwr-spin-button:disabled {
    background: #95a5a6;
    cursor: not-allowed;
    transform: translate(-50%, -50%) scale(1);
}

.lwr-sidebar {
    flex: 1;
    min-width: 300px;
    padding: 20px;
    background: #f8f9fa;
    border-radius: 10px;
    margin-left: 20px;
}

.lwr-prize-list, .lwr-user-info, .lwr-winning-history {
    margin-bottom: 30px;
    padding: 15px;
    background: white;
    border-radius: 8px;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
}

/* 响应式设计 */
@media (max-width: 768px) {
    .lwr-container {
        flex-direction: column;
    }
    
    .lwr-sidebar {
        margin-left: 0;
        margin-top: 20px;
    }
    
    .lwr-wheel-wrapper {
        max-width: 100%;
    }
}

5.3 JavaScript交互逻辑

// assets/js/lucky-wheel.js
class LuckyWheel {
    constructor() {
        this.canvas = document.getElementById('lucky-wheel-canvas');
        this.ctx = this.canvas.getContext('2d');
        this.spinButton = document.getElementById('spin-button');
        this.resultModal = document.getElementById('result-modal');
        this.remainingAttempts = document.getElementById('remaining-attempts');
        this.totalAttempts = document.getElementById('total-attempts');
        
        this.prizes = [];
        this.isSpinning = false;
        this.currentRotation = 0;
        this.wheelRadius = Math.min(this.canvas.width, this.canvas.height) / 2;
        this.centerX = this.canvas.width / 2;
        this.centerY = this.canvas.height / 2;
        
        this.init();
    }
    
    async init() {
        // 加载奖品数据
        await this.loadPrizes();
        
        // 绘制转盘
        this.drawWheel();
        
        // 绑定事件
        this.bindEvents();
        
        // 加载用户数据
        this.loadUserData();
    }
    
    async loadPrizes() {
        try {
            const response = await fetch('/wp-json/lwr/v1/prizes');
            this.prizes = await response.json();
            this.updatePrizeList();
        } catch (error) {
            console.error('加载奖品数据失败:', error);
        }
    }
    
    drawWheel() {
        const ctx = this.ctx;
        const totalPrizes = this.prizes.length;
        const angleStep = (2 * Math.PI) / totalPrizes;
        
        // 清空画布
        ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        
        // 绘制转盘扇形
        for (let i = 0; i < totalPrizes; i++) {
            const startAngle = i * angleStep + this.currentRotation;
            const endAngle = (i + 1) * angleStep + this.currentRotation;
            
            // 交替颜色
            const color = i % 2 === 0 ? '#3498db' : '#2ecc71';
            
            // 绘制扇形
            ctx.beginPath();
            ctx.moveTo(this.centerX, this.centerY);
            ctx.arc(this.centerX, this.centerY, this.wheelRadius, startAngle, endAngle);
            ctx.closePath();
            ctx.fillStyle = color;
            ctx.fill();
            ctx.strokeStyle = '#fff';
            ctx.lineWidth = 2;
            ctx.stroke();
            
            // 绘制奖品文字
            ctx.save();
            ctx.translate(this.centerX, this.centerY);
            ctx.rotate(startAngle + angleStep / 2);
            ctx.textAlign = 'right';
            ctx.fillStyle = '#fff';
            ctx.font = 'bold 16px Arial';
            ctx.fillText(this.prizes[i].name, this.wheelRadius - 20, 10);
            ctx.restore();
        }
        
        // 绘制中心圆
        ctx.beginPath();
        ctx.arc(this.centerX, this.centerY, 30, 0, 2 * Math.PI);
        ctx.fillStyle = '#e74c3c';
        ctx.fill();
        ctx.strokeStyle = '#fff';
        ctx.lineWidth = 4;
        ctx.stroke();
    }
    
    bindEvents() {
        this.spinButton.addEventListener('click', () => this.spinWheel());
        
        // 关闭弹窗
        document.querySelector('.lwr-close-modal').addEventListener('click', () => {
            this.resultModal.style.display = 'none';
        });
        
        // 领取奖品按钮
        document.getElementById('claim-prize').addEventListener('click', () => {
    });
}

async spinWheel() {
    if (this.isSpinning) return;
    
    // 检查抽奖次数
    const remaining = parseInt(this.remainingAttempts.textContent);
    if (remaining <= 0) {
        alert('今日抽奖次数已用完!');
        return;
    }
    
    this.isSpinning = true;
    this.spinButton.disabled = true;
    
    // 发送抽奖请求
    try {
        const response = await fetch('/wp-json/lwr/v1/spin', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-WP-Nonce': lwr_ajax.nonce
            },
            body: JSON.stringify({})
        });
        
        const result = await response.json();
        
        if (result.success) {
            // 执行转盘动画
            await this.animateWheel(result.prize_index);
            
            // 显示中奖结果
            this.showResult(result.prize);
            
            // 更新用户数据
            this.updateUserData(result.user_data);
        } else {
            alert(result.message || '抽奖失败,请重试!');
            this.isSpinning = false;
            this.spinButton.disabled = false;
        }
    } catch (error) {
        console.error('抽奖请求失败:', error);
        this.isSpinning = false;
        this.spinButton.disabled = false;
    }
}

animateWheel(prizeIndex) {
    return new Promise((resolve) => {
        const totalPrizes = this.prizes.length;
        const targetRotation = this.currentRotation + 5 * Math.PI + (prizeIndex * (2 * Math.PI / totalPrizes));
        
        const duration = 5000; // 动画持续时间(毫秒)
        const startTime = Date.now();
        const startRotation = this.currentRotation;
        
        const animate = () => {
            const elapsed = Date.now() - startTime;
            const progress = Math.min(elapsed / duration, 1);
            
            // 缓动函数,使动画先快后慢
            const easeOut = 1 - Math.pow(1 - progress, 3);
            
            this.currentRotation = startRotation + (targetRotation - startRotation) * easeOut;
            this.drawWheel();
            
            if (progress < 1) {
                requestAnimationFrame(animate);
            } else {
                this.isSpinning = false;
                this.spinButton.disabled = false;
                resolve();
            }
        };
        
        animate();
    });
}

showResult(prize) {
    const resultTitle = document.getElementById('result-title');
    const resultDetails = document.getElementById('result-details');
    
    if (prize.name === '谢谢参与') {
        resultTitle.textContent = '很遗憾,未中奖';
        resultDetails.innerHTML = `
            <p>您抽中了: <strong>${prize.name}</strong></p>
            <p>不要灰心,明天再来试试!</p>
        `;
    } else {
        resultTitle.textContent = '恭喜您中奖了!';
        resultDetails.innerHTML = `
            <div class="prize-result">
                <h3>${prize.name}</h3>
                <p>${prize.description || ''}</p>
                <p class="prize-value">奖品价值: ${prize.value || '无'}</p>
            </div>
        `;
    }
    
    this.resultModal.style.display = 'block';
}

updateUserData(userData) {
    if (userData.remaining_attempts !== undefined) {
        this.remainingAttempts.textContent = userData.remaining_attempts;
    }
    if (userData.total_attempts !== undefined) {
        this.totalAttempts.textContent = userData.total_attempts;
    }
}

updatePrizeList() {
    const prizeList = document.getElementById('prize-list');
    prizeList.innerHTML = '';
    
    this.prizes.forEach(prize => {
        const li = document.createElement('li');
        li.className = 'prize-item';
        li.innerHTML = `
            <span class="prize-name">${prize.name}</span>
            <span class="prize-probability">${(prize.probability * 100).toFixed(2)}%</span>
            ${prize.stock > 0 ? `<span class="prize-stock">剩余: ${prize.stock}</span>` : ''}
        `;
        prizeList.appendChild(li);
    });
}

async loadUserData() {
    try {
        const response = await fetch('/wp-json/lwr/v1/user-data');
        const data = await response.json();
        
        if (data.success) {
            this.updateUserData(data.data);
        }
    } catch (error) {
        console.error('加载用户数据失败:', error);
    }
}

async claimPrize() {
    // 领取奖品的逻辑
    alert('奖品领取功能开发中...');
    this.resultModal.style.display = 'none';
}

}

// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {

new LuckyWheel();

});


## 6. 后端开发:抽奖逻辑与数据管理

### 6.1 抽奖逻辑实现

// includes/class-lottery-logic.php
class LWR_Lottery_Logic {

private $db;

public function __construct() {
    $this->db = LWR_Database::get_instance();
}

/**
 * 执行抽奖逻辑
 */
public function spin_wheel($user_id = 0) {
    // 检查用户抽奖资格
    $can_spin = $this->check_user_eligibility($user_id);
    if (!$can_spin['success']) {
        return $can_spin;
    }
    
    // 获取可用奖品
    $available_prizes = $this->get_available_prizes();
    if (empty($available_prizes)) {
        return array(
            'success' => false,
            'message' => '暂无可用奖品'
        );
    }
    
    // 根据概率计算中奖奖品
    $winning_prize = $this->calculate_winning_prize($available_prizes);
    
    // 记录抽奖结果
    $record_id = $this->record_spin_result($user_id, $winning_prize);
    
    if (!$record_id) {
        return array(
            'success' => false,
            'message' => '记录抽奖结果失败'
        );
    }
    
    // 更新用户抽奖次数
    $this->update_user_attempts($user_id);
    
    // 更新奖品库存
    if ($winning_prize->id && $winning_prize->stock > 0) {
        $this->update_prize_stock($winning_prize->id);
    }
    
    // 准备返回数据
    $prize_index = array_search($winning_prize, array_values($available_prizes));
    
    return array(
        'success' => true,
        'prize' => $winning_prize,
        'prize_index' => $prize_index,
        'user_data' => $this->get_user_spin_data($user_id)
    );
}

/**
 * 检查用户抽奖资格
 */
private function check_user_eligibility($user_id) {
    global $wpdb;
    
    // 检查IP限制(防止刷奖)
    $ip_address = $this->get_client_ip();
    $today = date('Y-m-d');
    
    // 同一IP今日抽奖次数限制
    $ip_attempts = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM {$wpdb->prefix}lwr_records 
         WHERE ip_address = %s AND DATE(created_at) = %s",
        $ip_address, $today
    ));
    
    if ($ip_attempts >= 10) { // IP限制10次/天
        return array(
            'success' => false,
            'message' => '今日抽奖次数已达上限'
        );
    }
    
    // 注册用户检查
    if ($user_id > 0) {
        $user_attempts = $this->get_user_attempts($user_id);
        
        // 每日次数限制
        if ($user_attempts['attempts_today'] >= 5) {
            return array(
                'success' => false,
                'message' => '您今日的抽奖次数已用完'
            );
        }
        
        // 总次数限制
        if ($user_attempts['total_attempts'] >= 100) {
            return array(
                'success' => false,
                'message' => '您的总抽奖次数已用完'
            );
        }
    } else {
        // 未登录用户限制
        $guest_attempts = $this->get_guest_attempts($ip_address);
        if ($guest_attempts >= 3) {
            return array(
                'success' => false,
                'message' => '请登录后继续抽奖'
            );
        }
    }
    
    return array('success' => true);
}

/**
 * 获取可用奖品列表
 */
private function get_available_prizes() {
    global $wpdb;
    
    $today = date('Y-m-d');
    
    $prizes = $wpdb->get_results(
        "SELECT p.*, 
         (SELECT COUNT(*) FROM {$wpdb->prefix}lwr_records r 
          WHERE r.prize_id = p.id AND DATE(r.created_at) = '{$today}') as today_wins
         FROM {$wpdb->prefix}lwr_prizes p
         WHERE p.stock > 0 OR p.stock = -1
         ORDER BY p.probability ASC"
    );
    
    // 过滤掉达到每日限制的奖品
    $available_prizes = array();
    foreach ($prizes as $prize) {
        if ($prize->daily_limit == 0 || $prize->today_wins < $prize->daily_limit) {
            $available_prizes[] = $prize;
        }
    }
    
    // 确保至少有一个"谢谢参与"选项
    $has_thank_you = false;
    foreach ($available_prizes as $prize) {
        if (strpos($prize->name, '谢谢参与') !== false) {
            $has_thank_you = true;
            break;
        }
    }
    
    if (!$has_thank_you) {
        $thank_you_prize = (object) array(
            'id' => 0,
            'name' => '谢谢参与',
            'description' => '感谢参与,下次好运!',
            'probability' => 0.5,
            'stock' => -1,
            'type' => 'virtual'
        );
        array_push($available_prizes, $thank_you_prize);
    }
    
    return $available_prizes;
}

/**
 * 根据概率计算中奖奖品
 */
private function calculate_winning_prize($prizes) {
    // 计算总概率
    $total_probability = 0;
    foreach ($prizes as $prize) {
        $total_probability += floatval($prize->probability);
    }
    
    // 生成随机数
    $random = mt_rand() / mt_getrandmax() * $total_probability;
    
    // 根据概率选择奖品
    $current_probability = 0;
    foreach ($prizes as $prize) {
        $current_probability += floatval($prize->probability);
        if ($random <= $current_probability) {
            return $prize;
        }
    }
    
    // 默认返回最后一个奖品(谢谢参与)
    return end($prizes);
}

/**
 * 获取客户端IP
 */
private function get_client_ip() {
    $ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR');
    
    foreach ($ip_keys as $key) {
        if (array_key_exists($key, $_SERVER) === true) {
            foreach (explode(',', $_SERVER[$key]) as $ip) {
                $ip = trim($ip);
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                    return $ip;
                }
            }
        }
    }
    
    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}

// 其他辅助方法...

}


### 6.2 REST API端点注册

// 在主插件文件中添加
add_action('rest_api_init', function() {

// 获取奖品列表
register_rest_route('lwr/v1', '/prizes', array(
    'methods' => 'GET',
    'callback' => 'lwr_api_get_prizes',
    'permission_callback' => '__return_true'
));

// 执行抽奖
register_rest_route('lwr/v1', '/spin', array(
    'methods' => 'POST',
    'callback' => 'lwr_api_spin_wheel',
    'permission_callback' => function() {
        return is_user_logged_in() || $this->check_guest_permission();
    }
));

// 获取用户数据
register_rest_route('lwr/v1', '/user-data', array(
    'methods' => 'GET',
    'callback' => 'lwr_api_get_user_data',
    'permission_callback' => '__return_true'
));

});

function lwr_api_get_prizes() {

$db = LWR_Database::get_instance();
$prizes = $db->get_prizes();

return new WP_REST_Response(array(
    'success' => true,
    'data' => $prizes
), 200);

}

function lwr_api_spin_wheel($request) {

$user_id = get_current_user_id();
$logic = new LWR_Lottery_Logic();
$result = $logic->spin_wheel($user_id);

return new WP_REST_Response($result, $result['success'] ? 200 : 400);

}

function lwr_api_get_user_data($request) {

$user_id = get_current_user_id();
$logic = new LWR_Lottery_Logic();
$user_data = $logic->get_user_spin_data($user_id);

return new WP_REST_Response(array(
    'success' => true,
    'data' => $user_data
), 200);

}


## 7. WordPress集成与插件化开发

### 7.1 主插件文件结构

<?php
/**

  • Plugin Name: 幸运大转盘抽奖系统
  • Plugin URI: https://yourwebsite.com/lucky-wheel
  • Description: 为WordPress网站添加在线抽奖和幸运大转盘功能
  • Version: 1.0.0
  • Author: Your Name
  • License: GPL v2 or later
    */

// 防止直接访问
if (!defined('ABSPATH')) {

exit;

}

// 定义插件常量
define('LWR_VERSION', '1.0.0');
define('LWR_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('LWR_PLUGIN_URL', plugin_dir_url(__FILE__));

// 自动加载类文件
spl_autoload_register(function($class_name) {

if (strpos($class_name, 'LWR_') === 0) {
    $file = LWR_PLUGIN_DIR . 'includes/' . 'class-' . strtolower(str_replace('_', '-', $class_name)) . '.php';
    if (file_exists($file)) {
        require_once $file;
    }
}

});

// 初始化插件
class Lucky_Wheel_Roulette {

private static $instance = null;

public static function get_instance() {
    if (null === self::$instance) {
        self::$instance = new self();
    }
    return self::$instance;
}

private function __construct() {
    $this->init_hooks();
}

private function init_hooks() {
    // 激活/停用钩子
    register_activation_hook(__FILE__, array($this, 'activate'));
    register_deactivation_hook(__FILE__, array($this, 'deactivate'));
    
    // 初始化
    add_action('plugins_loaded', array($this, 'init'));
    
    // 添加短代码
    add_shortcode('lucky_wheel', array($this, 'shortcode_handler'));
    
    // 添加管理菜单
    add_action('admin_menu', array($this, 'add_admin_menu'));
    
    // 加载脚本和样式
    add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
    add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
}

public function activate() {
    // 创建数据库表
    $db = LWR_Database::get_instance();
    $db->create_tables();
    
    // 设置默认选项
    $default_options = array(
        'daily_limit_logged_in' => 5,
        'daily_limit_guest' => 3,
        'enable_sound' => true,
        'wheel_colors' => array('#3498db', '#2ecc71', '#e74c3c', '#f39c12'),
        'require_email' => false
    );
    
    add_option('lwr_settings', $default_options);
    
    // 创建必要的页面
    $this->create_pages();
}

public function deactivate() {
    // 清理临时数据
    // 注意:不删除用户数据和设置
}

public function init() {
    // 初始化组件
    if (is_admin()) {
        new LWR_Admin_Panel();
    }
}

public function shortcode_handler($atts) {
    $atts = shortcode_atts(array(
        'width' => '100%',
        '
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5208.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部