文章目录[隐藏]
开发指南:打造网站内嵌的在线抽奖与幸运大转盘互动营销组件
摘要
在当今数字营销时代,互动式营销工具已成为提升用户参与度和转化率的关键手段。本文将详细介绍如何通过WordPress程序的代码二次开发,实现一个功能完整的在线抽奖与幸运大转盘互动营销组件。我们将从需求分析、技术选型、代码实现到部署测试,全面解析开发流程,帮助开发者快速构建这一常用互联网小工具功能。
目录
- 引言:互动营销组件的重要性
- 需求分析与功能规划
- 技术架构与开发环境搭建
- 数据库设计与数据模型
- 前端实现:转盘界面与交互设计
- 后端开发:抽奖逻辑与数据管理
- WordPress集成与插件化开发
- 安全性与性能优化
- 测试与部署策略
- 维护与扩展建议
- 结语:未来发展方向
1. 引言:互动营销组件的重要性
在竞争激烈的互联网环境中,网站需要不断创新以吸引和留住用户。互动营销组件,如在线抽奖和幸运大转盘,已成为提升用户参与度、增加页面停留时间、促进转化的有效工具。这些组件不仅能够增强用户体验,还能为网站运营者提供宝贵的用户行为数据。
WordPress作为全球最流行的内容管理系统,拥有庞大的用户基础和丰富的扩展生态。通过二次开发,我们可以将定制化的互动营销组件无缝集成到WordPress网站中,满足特定业务需求,同时保持与现有主题和插件的兼容性。
2. 需求分析与功能规划
2.1 核心功能需求
- 转盘可视化界面:美观、可自定义的转盘界面,支持多种奖品设置
- 抽奖逻辑系统:可配置的中奖概率、奖品库存管理
- 用户参与管理:用户身份验证、参与次数限制、中奖记录
- 数据统计与分析:参与数据、中奖率、用户行为分析
- 后台管理界面:奖品管理、概率设置、数据监控
2.2 非功能性需求
- 响应式设计:适配各种设备屏幕尺寸
- 性能优化:快速加载和流畅的动画效果
- 安全性:防止作弊和恶意攻击
- 可扩展性:便于未来功能扩展和定制
2.3 用户角色与权限
- 网站管理员:完全控制抽奖设置和数据管理
- 编辑人员:管理奖品内容和基本设置
- 普通用户:参与抽奖活动,查看中奖记录
- 未注册访客:有限次数的参与机会
3. 技术架构与开发环境搭建
3.1 技术选型
- 前端技术:HTML5、CSS3、JavaScript (ES6+)、Canvas/SVG(转盘绘制)
- 动画库:GSAP或CSS3动画实现流畅转盘效果
- 后端技术:PHP 7.4+(WordPress核心语言)
- 数据库:MySQL(WordPress默认数据库)
- WordPress开发:遵循WordPress插件开发规范
3.2 开发环境配置
- 本地开发环境:安装XAMPP/MAMP或Local by Flywheel
- WordPress安装:最新稳定版WordPress
- 代码编辑器:VS Code或PHPStorm
- 版本控制:Git
- 调试工具:浏览器开发者工具、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">×</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%',
'
