首页 / 应用软件 / 详细指南,开发网站会员签到打卡与连续奖励积分系统

详细指南,开发网站会员签到打卡与连续奖励积分系统

详细指南:开发网站会员签到打卡与连续奖励积分系统

摘要

在当今互联网时代,用户参与度和忠诚度是网站成功的关键因素之一。会员签到打卡与连续奖励积分系统作为一种有效的用户激励工具,已被广泛应用于各类网站和应用程序中。本文将详细介绍如何通过WordPress程序的代码二次开发,实现一个功能完善的会员签到打卡与连续奖励积分系统。我们将从系统设计、数据库结构、核心功能实现、用户界面设计到系统测试与优化,全面解析开发过程,帮助开发者快速掌握这一常用互联网小工具的实现方法。


第一章:系统概述与设计思路

1.1 签到打卡系统的价值

签到打卡系统是一种简单而有效的用户参与机制,通过每日签到获取积分奖励的方式,鼓励用户养成访问网站的习惯。这种系统不仅提高了用户粘性,还能促进内容消费和社区互动。结合连续签到奖励机制,用户为了获得更高的积分奖励,会努力保持连续签到记录,从而形成良性的用户行为循环。

1.2 系统功能需求分析

一个完整的会员签到打卡与连续奖励积分系统应包含以下核心功能:

  1. 用户签到功能:允许用户每日签到一次,记录签到时间
  2. 连续签到追踪:跟踪用户连续签到天数,并在中断时重置
  3. 积分奖励机制:根据签到情况奖励相应积分,连续签到天数越多奖励越高
  4. 签到日历展示:可视化展示用户的签到历史记录
  5. 奖励规则配置:管理员可灵活配置积分奖励规则
  6. 用户数据统计:展示用户的签到统计信息
  7. 积分兑换功能:允许用户使用积分兑换虚拟或实物奖励

1.3 WordPress二次开发的优势

WordPress作为全球最流行的内容管理系统,拥有以下优势:

  • 成熟的用户管理系统
  • 丰富的插件架构和钩子机制
  • 庞大的开发者社区支持
  • 灵活的主题和插件扩展能力
  • 良好的安全性和稳定性

通过WordPress二次开发实现签到系统,可以充分利用现有用户体系,减少重复开发工作,提高开发效率。


第二章:数据库设计与数据模型

2.1 数据表结构设计

为了实现签到打卡系统,我们需要在WordPress数据库中添加以下自定义数据表:

-- 用户签到记录表
CREATE TABLE wp_signin_records (
    id INT(11) NOT NULL AUTO_INCREMENT,
    user_id INT(11) NOT NULL,
    signin_date DATE NOT NULL,
    signin_time DATETIME NOT NULL,
    continuous_days INT(11) DEFAULT 1,
    points_earned INT(11) DEFAULT 0,
    PRIMARY KEY (id),
    UNIQUE KEY user_date (user_id, signin_date),
    KEY user_id (user_id),
    KEY signin_date (signin_date)
);

-- 用户积分总表
CREATE TABLE wp_user_points (
    id INT(11) NOT NULL AUTO_INCREMENT,
    user_id INT(11) NOT NULL,
    total_points INT(11) DEFAULT 0,
    available_points INT(11) DEFAULT 0,
    last_updated DATETIME NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY user_id (user_id)
);

-- 积分奖励规则表
CREATE TABLE wp_points_rules (
    id INT(11) NOT NULL AUTO_INCREMENT,
    rule_name VARCHAR(100) NOT NULL,
    continuous_days INT(11) NOT NULL,
    points_award INT(11) NOT NULL,
    is_active TINYINT(1) DEFAULT 1,
    PRIMARY KEY (id)
);

-- 积分兑换记录表
CREATE TABLE wp_points_redemption (
    id INT(11) NOT NULL AUTO_INCREMENT,
    user_id INT(11) NOT NULL,
    redemption_date DATETIME NOT NULL,
    points_used INT(11) NOT NULL,
    item_name VARCHAR(200) NOT NULL,
    status VARCHAR(50) DEFAULT 'pending',
    PRIMARY KEY (id),
    KEY user_id (user_id)
);

2.2 数据关系与索引优化

为了提高查询效率,我们在关键字段上建立了索引:

  • wp_signin_records表的user_idsignin_date字段建立联合唯一索引,防止重复签到
  • 各表的user_id字段建立普通索引,加快用户相关查询
  • signin_date字段建立索引,便于按日期范围查询统计

2.3 与WordPress用户表的关联

我们的签到系统需要与WordPress核心用户表wp_users进行关联,通过user_id字段建立外键关系,确保数据一致性。同时,我们可以利用WordPress的用户元数据表wp_usermeta存储一些额外的用户签到相关信息。


第三章:核心功能实现

3.1 签到功能模块

3.1.1 签到逻辑实现

<?php
/**
 * 处理用户签到
 */
function handle_user_signin($user_id) {
    global $wpdb;
    
    // 检查用户是否已签到
    $today = date('Y-m-d');
    $table_name = $wpdb->prefix . 'signin_records';
    
    $already_signed = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM $table_name WHERE user_id = %d AND signin_date = %s",
        $user_id, $today
    ));
    
    if ($already_signed > 0) {
        return array(
            'success' => false,
            'message' => '今日已签到,请明天再来!'
        );
    }
    
    // 获取用户昨日签到记录,计算连续签到天数
    $yesterday = date('Y-m-d', strtotime('-1 day'));
    $yesterday_record = $wpdb->get_row($wpdb->prepare(
        "SELECT continuous_days FROM $table_name WHERE user_id = %d AND signin_date = %s",
        $user_id, $yesterday
    ));
    
    $continuous_days = 1;
    if ($yesterday_record) {
        $continuous_days = $yesterday_record->continuous_days + 1;
    }
    
    // 根据连续签到天数计算奖励积分
    $points_earned = calculate_signin_points($continuous_days);
    
    // 插入签到记录
    $result = $wpdb->insert(
        $table_name,
        array(
            'user_id' => $user_id,
            'signin_date' => $today,
            'signin_time' => current_time('mysql'),
            'continuous_days' => $continuous_days,
            'points_earned' => $points_earned
        ),
        array('%d', '%s', '%s', '%d', '%d')
    );
    
    if ($result) {
        // 更新用户总积分
        update_user_points($user_id, $points_earned);
        
        return array(
            'success' => true,
            'message' => '签到成功!',
            'continuous_days' => $continuous_days,
            'points_earned' => $points_earned
        );
    } else {
        return array(
            'success' => false,
            'message' => '签到失败,请稍后重试!'
        );
    }
}

/**
 * 根据连续签到天数计算奖励积分
 */
function calculate_signin_points($continuous_days) {
    $base_points = 10; // 基础积分
    
    // 连续签到额外奖励
    $extra_points = 0;
    if ($continuous_days >= 7) {
        $extra_points = 30;
    } elseif ($continuous_days >= 30) {
        $extra_points = 100;
    } elseif ($continuous_days >= 100) {
        $extra_points = 500;
    }
    
    // 特殊日期额外奖励(如节假日)
    $special_bonus = check_special_date_bonus();
    
    return $base_points + $extra_points + $special_bonus;
}
?>

3.1.2 AJAX签到接口

<?php
/**
 * 注册AJAX签到接口
 */
add_action('wp_ajax_user_signin', 'ajax_handle_signin');
add_action('wp_ajax_nopriv_user_signin', 'ajax_handle_signin_no_priv');

function ajax_handle_signin() {
    // 验证用户登录状态
    if (!is_user_logged_in()) {
        wp_send_json_error('请先登录!');
    }
    
    $user_id = get_current_user_id();
    $result = handle_user_signin($user_id);
    
    if ($result['success']) {
        wp_send_json_success($result);
    } else {
        wp_send_json_error($result['message']);
    }
}

function ajax_handle_signin_no_priv() {
    wp_send_json_error('请先登录!');
}
?>

3.2 连续签到追踪模块

<?php
/**
 * 获取用户连续签到天数
 */
function get_user_continuous_days($user_id) {
    global $wpdb;
    
    $table_name = $wpdb->prefix . 'signin_records';
    $today = date('Y-m-d');
    
    // 获取今日签到记录
    $today_record = $wpdb->get_row($wpdb->prepare(
        "SELECT continuous_days FROM $table_name WHERE user_id = %d AND signin_date = %s",
        $user_id, $today
    ));
    
    if ($today_record) {
        return $today_record->continuous_days;
    }
    
    // 如果今日未签到,检查昨日是否签到
    $yesterday = date('Y-m-d', strtotime('-1 day'));
    $yesterday_record = $wpdb->get_row($wpdb->prepare(
        "SELECT continuous_days FROM $table_name WHERE user_id = %d AND signin_date = %s",
        $user_id, $yesterday
    ));
    
    if ($yesterday_record) {
        return 0; // 今日未签到,但昨日已签到,连续天数中断
    }
    
    // 检查连续签到是否中断
    return check_continuous_break($user_id);
}

/**
 * 检查连续签到是否中断
 */
function check_continuous_break($user_id) {
    global $wpdb;
    
    $table_name = $wpdb->prefix . 'signin_records';
    
    // 获取最近一次签到记录
    $latest_record = $wpdb->get_row($wpdb->prepare(
        "SELECT signin_date, continuous_days FROM $table_name 
         WHERE user_id = %d ORDER BY signin_date DESC LIMIT 1",
        $user_id
    ));
    
    if (!$latest_record) {
        return 0; // 从未签到
    }
    
    $last_signin_date = $latest_record->signin_date;
    $days_since_last = floor((time() - strtotime($last_signin_date)) / (60 * 60 * 24));
    
    // 如果距离上次签到超过1天,则连续签到中断
    if ($days_since_last > 1) {
        return 0;
    }
    
    return $latest_record->continuous_days;
}
?>

3.3 积分管理系统

<?php
/**
 * 更新用户积分
 */
function update_user_points($user_id, $points_to_add) {
    global $wpdb;
    
    $table_name = $wpdb->prefix . 'user_points';
    
    // 检查用户积分记录是否存在
    $existing_record = $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM $table_name WHERE user_id = %d",
        $user_id
    ));
    
    if ($existing_record) {
        // 更新现有记录
        $new_total = $existing_record->total_points + $points_to_add;
        $new_available = $existing_record->available_points + $points_to_add;
        
        $wpdb->update(
            $table_name,
            array(
                'total_points' => $new_total,
                'available_points' => $new_available,
                'last_updated' => current_time('mysql')
            ),
            array('user_id' => $user_id),
            array('%d', '%d', '%s'),
            array('%d')
        );
    } else {
        // 创建新记录
        $wpdb->insert(
            $table_name,
            array(
                'user_id' => $user_id,
                'total_points' => $points_to_add,
                'available_points' => $points_to_add,
                'last_updated' => current_time('mysql')
            ),
            array('%d', '%d', '%d', '%s')
        );
    }
    
    // 记录积分变动日志
    log_points_change($user_id, $points_to_add, 'signin_reward', '签到奖励');
}

/**
 * 积分兑换功能
 */
function redeem_points($user_id, $item_id, $points_required) {
    global $wpdb;
    
    // 检查用户可用积分
    $user_points = $wpdb->get_row($wpdb->prepare(
        "SELECT available_points FROM {$wpdb->prefix}user_points WHERE user_id = %d",
        $user_id
    ));
    
    if (!$user_points || $user_points->available_points < $points_required) {
        return array(
            'success' => false,
            'message' => '积分不足,无法兑换!'
        );
    }
    
    // 获取兑换物品信息
    $item_info = get_redemption_item($item_id);
    if (!$item_info) {
        return array(
            'success' => false,
            'message' => '兑换物品不存在!'
        );
    }
    
    // 开始事务处理
    $wpdb->query('START TRANSACTION');
    
    try {
        // 扣除用户积分
        $wpdb->query($wpdb->prepare(
            "UPDATE {$wpdb->prefix}user_points 
             SET available_points = available_points - %d 
             WHERE user_id = %d",
            $points_required, $user_id
        ));
        
        // 记录兑换记录
        $wpdb->insert(
            $wpdb->prefix . 'points_redemption',
            array(
                'user_id' => $user_id,
                'redemption_date' => current_time('mysql'),
                'points_used' => $points_required,
                'item_name' => $item_info['name'],
                'status' => 'pending'
            ),
            array('%d', '%s', '%d', '%s', '%s')
        );
        
        $wpdb->query('COMMIT');
        
        return array(
            'success' => true,
            'message' => '兑换成功,请等待管理员处理!'
        );
    } catch (Exception $e) {
        $wpdb->query('ROLLBACK');
        return array(
            'success' => false,
            'message' => '兑换失败:' . $e->getMessage()
        );
    }
}
?>

第四章:用户界面设计与实现

4.1 签到界面设计

<?php
/**
 * 签到界面短代码
 */
add_shortcode('signin_system', 'display_signin_system');

function display_signin_system() {
    if (!is_user_logged_in()) {
        return '<div class="signin-notice">请先登录以使用签到功能</div>';
    }
    
    $user_id = get_current_user_id();
    $user_info = get_userdata($user_id);
    $continuous_days = get_user_continuous_days($user_id);
    $today_signed = check_today_signin($user_id);
    
    ob_start();
    ?>
    <div class="signin-container">
        <div class="signin-header">
            <h2>每日签到</h2>
            <p>连续签到可获得更多积分奖励</p>
        </div>
        
        <div class="user-stats">
            <div class="stat-item">
                <span class="stat-label">用户名</span>
                <span class="stat-value"><?php echo esc_html($user_info->display_name); ?></span>
            </div>
            <div class="stat-item">
                <span class="stat-label">连续签到</span>
                <span class="stat-value"><?php echo $continuous_days; ?> 天</span>
            </div>
            <div class="stat-item">
                <span class="stat-label">总积分</span>
                <span class="stat-value"><?php echo get_user_total_points($user_id); ?></span>
            </div>
        </div>
        
        <div class="signin-main">
            <?php if ($today_signed): ?>
                <div class="signin-already">
                    <div class="signin-icon">✓</div>
                    <h3>今日已签到</h3>
                    <p>您已连续签到 <?php echo $continuous_days; ?> 天</p>
                    <p>明日再来可获得更多积分!</p>
                </div>
            <?php else: ?>
                <div class="signin-available" id="signin-box">
                    <div class="signin-icon">📅</div>
                    <h3>立即签到</h3>
                    <p>今日签到可获得 <span class="points-preview"><?php echo calculate_signin_points($continuous_days + 1); ?></span> 积分</p>
                    <button class="signin-button" id="signin-button">立即签到</button>
                    <div class="signin-loading" id="signin-loading" style="display:none;">
                        处理中...
                    </div>
                </div>
            <?php endif; ?>
        </div>
        
        <div class="signin-calendar">
            <h3>签到日历</h3>
            <?php display_signin_calendar($user_id); ?>
        </div>
        
        <div class="rewards-info">
            <h3>连续签到奖励规则</h3>
            <ul class="rewards-list">
                <li>第1-6天:每天10积分</li>
                <li>第7天:额外奖励30积分</li>
                <li>第30天:额外奖励100积分</li>
                <li>第100天:额外奖励500积分</li>
                <li>节假日:额外奖励20积分</li>
            </ul>
        </div>
    </div>
    
    <script>
    jQuery(document).ready(function($) {
        $('#signin-button').click(function() {
            var button = $(this);
            var loading = $('#signin-loading');
            

button.prop('disabled', true).text('签到中...');

        loading.show();
        
        $.ajax({
            url: '<?php echo admin_url('admin-ajax.php'); ?>',
            type: 'POST',
            data: {
                action: 'user_signin',
                nonce: '<?php echo wp_create_nonce('signin_nonce'); ?>'
            },
            success: function(response) {
                if (response.success) {
                    // 更新界面显示
                    $('#signin-box').html(`
                        <div class="signin-success">
                            <div class="signin-icon">🎉</div>
                            <h3>签到成功!</h3>
                            <p>获得 <span class="points-earned">${response.data.points_earned}</span> 积分</p>
                            <p>连续签到天数:${response.data.continuous_days} 天</p>
                            <p>明日签到可获得更多积分!</p>
                        </div>
                    `);
                    
                    // 更新用户统计信息
                    setTimeout(function() {
                        location.reload();
                    }, 2000);
                } else {
                    alert(response.data);
                    button.prop('disabled', false).text('立即签到');
                    loading.hide();
                }
            },
            error: function() {
                alert('签到失败,请稍后重试!');
                button.prop('disabled', false).text('立即签到');
                loading.hide();
            }
        });
    });
});
</script>
<?php

return ob_get_clean();

}

/**

  • 显示签到日历
    */

function display_signin_calendar($user_id) {

global $wpdb;

$table_name = $wpdb->prefix . 'signin_records';
$current_month = date('n');
$current_year = date('Y');

// 获取本月签到记录
$signin_records = $wpdb->get_results($wpdb->prepare(
    "SELECT DAY(signin_date) as day, points_earned 
     FROM $table_name 
     WHERE user_id = %d 
     AND MONTH(signin_date) = %d 
     AND YEAR(signin_date) = %d",
    $user_id, $current_month, $current_year
));

// 创建签到记录映射
$signin_map = array();
foreach ($signin_records as $record) {
    $signin_map[$record->day] = $record->points_earned;
}

// 生成日历
$first_day = mktime(0, 0, 0, $current_month, 1, $current_year);
$days_in_month = date('t', $first_day);
$first_day_of_week = date('w', $first_day);

ob_start();
?>
<div class="calendar">
    <div class="calendar-header">
        <span class="month-year"><?php echo date('Y年n月'); ?></span>
    </div>
    <div class="calendar-weekdays">
        <div>日</div>
        <div>一</div>
        <div>二</div>
        <div>三</div>
        <div>四</div>
        <div>五</div>
        <div>六</div>
    </div>
    <div class="calendar-days">
        <?php
        // 填充空白
        for ($i = 0; $i < $first_day_of_week; $i++) {
            echo '<div class="empty"></div>';
        }
        
        // 填充日期
        for ($day = 1; $day <= $days_in_month; $day++) {
            $is_today = ($day == date('j'));
            $has_signed = isset($signin_map[$day]);
            $class = 'day';
            
            if ($is_today) $class .= ' today';
            if ($has_signed) $class .= ' signed';
            
            echo '<div class="' . $class . '">';
            echo '<span class="day-number">' . $day . '</span>';
            
            if ($has_signed) {
                echo '<span class="signin-indicator" title="获得' . $signin_map[$day] . '积分">✓</span>';
            }
            
            echo '</div>';
        }
        ?>
    </div>
</div>
<?php
return ob_get_clean();

}
?>


### 4.2 用户积分中心

<?php
/**

  • 用户积分中心短代码
    */

add_shortcode('points_center', 'display_points_center');

function display_points_center() {

if (!is_user_logged_in()) {
    return '<div class="points-center-notice">请先登录以查看积分中心</div>';
}

$user_id = get_current_user_id();
$points_data = get_user_points_data($user_id);
$redemption_items = get_redemption_items();
$points_history = get_points_history($user_id, 10);

ob_start();
?>
<div class="points-center-container">
    <div class="points-overview">
        <div class="points-card">
            <h3>我的积分</h3>
            <div class="points-total">
                <span class="points-number"><?php echo $points_data['available_points']; ?></span>
                <span class="points-label">可用积分</span>
            </div>
            <div class="points-details">
                <div class="detail-item">
                    <span>总获得积分</span>
                    <span><?php echo $points_data['total_points']; ?></span>
                </div>
                <div class="detail-item">
                    <span>已使用积分</span>
                    <span><?php echo $points_data['total_points'] - $points_data['available_points']; ?></span>
                </div>
            </div>
        </div>
        
        <div class="points-actions">
            <h3>快速操作</h3>
            <button class="btn-checkin" onclick="location.href='#signin-system'">每日签到</button>
            <button class="btn-history" id="view-history">查看积分记录</button>
            <button class="btn-redeem" id="show-redeem-modal">积分兑换</button>
        </div>
    </div>
    
    <div class="points-history-section">
        <h3>最近积分记录</h3>
        <table class="points-history-table">
            <thead>
                <tr>
                    <th>日期</th>
                    <th>类型</th>
                    <th>积分变动</th>
                    <th>说明</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($points_history as $record): ?>
                <tr>
                    <td><?php echo date('Y-m-d H:i', strtotime($record->change_time)); ?></td>
                    <td><?php echo get_points_change_type_label($record->change_type); ?></td>
                    <td class="<?php echo $record->points_change >= 0 ? 'points-increase' : 'points-decrease'; ?>">
                        <?php echo ($record->points_change >= 0 ? '+' : '') . $record->points_change; ?>
                    </td>
                    <td><?php echo esc_html($record->description); ?></td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
    
    <div class="redemption-section">
        <h3>积分兑换商城</h3>
        <div class="redemption-items">
            <?php foreach ($redemption_items as $item): ?>
            <div class="redemption-item">
                <div class="item-image">
                    <img src="<?php echo esc_url($item['image']); ?>" alt="<?php echo esc_attr($item['name']); ?>">
                </div>
                <div class="item-info">
                    <h4><?php echo esc_html($item['name']); ?></h4>
                    <p class="item-description"><?php echo esc_html($item['description']); ?></p>
                    <div class="item-points">
                        <span class="points-required"><?php echo $item['points_required']; ?> 积分</span>
                        <?php if ($points_data['available_points'] >= $item['points_required']): ?>
                        <button class="btn-redeem-item" 
                                data-item-id="<?php echo $item['id']; ?>"
                                data-item-name="<?php echo esc_attr($item['name']); ?>"
                                data-points-required="<?php echo $item['points_required']; ?>">
                            立即兑换
                        </button>
                        <?php else: ?>
                        <button class="btn-redeem-item disabled" disabled>积分不足</button>
                        <?php endif; ?>
                    </div>
                </div>
            </div>
            <?php endforeach; ?>
        </div>
    </div>
</div>

<!-- 兑换确认模态框 -->
<div id="redeem-modal" class="modal">
    <div class="modal-content">
        <span class="close-modal">&times;</span>
        <h3>确认兑换</h3>
        <div id="redeem-item-info"></div>
        <div class="modal-actions">
            <button id="confirm-redeem" class="btn-confirm">确认兑换</button>
            <button id="cancel-redeem" class="btn-cancel">取消</button>
        </div>
    </div>
</div>

<script>
jQuery(document).ready(function($) {
    // 兑换按钮点击事件
    $('.btn-redeem-item').click(function() {
        var itemId = $(this).data('item-id');
        var itemName = $(this).data('item-name');
        var pointsRequired = $(this).data('points-required');
        
        $('#redeem-item-info').html(`
            <p>您要兑换:<strong>${itemName}</strong></p>
            <p>需要积分:<strong>${pointsRequired}</strong></p>
            <p>兑换后积分将立即扣除,兑换物品将在3个工作日内处理。</p>
        `);
        
        $('#redeem-modal').data('item-id', itemId);
        $('#redeem-modal').data('points-required', pointsRequired);
        $('#redeem-modal').show();
    });
    
    // 确认兑换
    $('#confirm-redeem').click(function() {
        var itemId = $('#redeem-modal').data('item-id');
        var pointsRequired = $('#redeem-modal').data('points-required');
        
        $.ajax({
            url: '<?php echo admin_url('admin-ajax.php'); ?>',
            type: 'POST',
            data: {
                action: 'redeem_points',
                item_id: itemId,
                points_required: pointsRequired,
                nonce: '<?php echo wp_create_nonce('redeem_nonce'); ?>'
            },
            success: function(response) {
                if (response.success) {
                    alert('兑换成功!');
                    location.reload();
                } else {
                    alert('兑换失败:' + response.data);
                }
            },
            error: function() {
                alert('兑换失败,请稍后重试!');
            }
        });
    });
    
    // 关闭模态框
    $('.close-modal, #cancel-redeem').click(function() {
        $('#redeem-modal').hide();
    });
});
</script>
<?php

return ob_get_clean();

}
?>


---

## 第五章:后台管理功能

### 5.1 管理菜单与界面

<?php
/**

  • 添加管理菜单
    */

add_action('admin_menu', 'register_signin_admin_menu');

function register_signin_admin_menu() {

add_menu_page(
    '签到管理系统',
    '签到管理',
    'manage_options',
    'signin-management',
    'display_signin_admin_page',
    'dashicons-calendar-alt',
    30
);

add_submenu_page(
    'signin-management',
    '签到记录',
    '签到记录',
    'manage_options',
    'signin-records',
    'display_signin_records_page'
);

add_submenu_page(
    'signin-management',
    '积分规则',
    '积分规则',
    'manage_options',
    'points-rules',
    'display_points_rules_page'
);

add_submenu_page(
    'signin-management',
    '兑换管理',
    '兑换管理',
    'manage_options',
    'redemption-management',
    'display_redemption_management_page'
);

add_submenu_page(
    'signin-management',
    '数据统计',
    '数据统计',
    'manage_options',
    'signin-statistics',
    'display_signin_statistics_page'
);

}

/**

  • 显示签到记录管理页面
    */

function display_signin_records_page() {

global $wpdb;

$table_name = $wpdb->prefix . 'signin_records';
$users_table = $wpdb->users;

// 处理搜索和筛选
$search = isset($_GET['s']) ? sanitize_text_field($_GET['s']) : '';
$date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : '';
$date_to = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : '';

// 构建查询条件
$where = array('1=1');
$query_params = array();

if (!empty($search)) {
    $where[] = "(u.user_login LIKE %s OR u.display_name LIKE %s)";
    $query_params[] = '%' . $wpdb->esc_like($search) . '%';
    $query_params[] = '%' . $wpdb->esc_like($search) . '%';
}

if (!empty($date_from)) {
    $where[] = "s.signin_date >= %s";
    $query_params[] = $date_from;
}

if (!empty($date_to)) {
    $where[] = "s.signin_date <= %s";
    $query_params[] = $date_to;
}

$where_clause = implode(' AND ', $where);

// 获取总记录数
$total_query = "SELECT COUNT(*) FROM $table_name s 
                INNER JOIN $users_table u ON s.user_id = u.ID 
                WHERE $where_clause";

if (!empty($query_params)) {
    $total_query = $wpdb->prepare($total_query, $query_params);
}

$total_items = $wpdb->get_var($total_query);

// 分页设置
$per_page = 20;
$current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
$offset = ($current_page - 1) * $per_page;

// 获取记录数据
$query = "SELECT s.*, u.user_login, u.display_name 
          FROM $table_name s 
          INNER JOIN $users_table u ON s.user_id = u.ID 
          WHERE $where_clause 
          ORDER BY s.signin_date DESC, s.signin_time DESC 
          LIMIT %d OFFSET %d";

$query_params[] = $per_page;
$query_params[] = $offset;

$records = $wpdb->get_results($wpdb->prepare($query, $query_params));

ob_start();
?>
<div class="wrap">
    <h1 class="wp-heading-inline">签到记录管理</h1>
    
    <form method="get" action="" class="search-form">
        <input type="hidden" name="page" value="signin-records">
        
        <div class="tablenav top">
            <div class="alignleft actions">
                <input type="text" name="s" value="<?php echo esc_attr($search); ?>" 
                       placeholder="搜索用户名或显示名称">
                
                <label>从:<input type="date" name="date_from" value="<?php echo esc_attr($date_from); ?>"></label>
                <label>到:<input type="date" name="date_to" value="<?php echo esc_attr($date_to); ?>"></label>
                
                <input type="submit" class="button" value="筛选">
                
                <?php if (!empty($search) || !empty($date_from) || !empty($date_to)): ?>
                <a href="?page=signin-records" class="button">清除筛选</a>
                <?php endif; ?>
            </div>
            
            <div class="tablenav-pages">
                <?php
                $total_pages = ceil($total_items / $per_page);
                echo paginate_links(array(
                    'base' => add_query_arg('paged', '%#%'),
                    'format' => '',
                    'prev_text' => '&laquo;',
                    'next_text' => '&raquo;',
                    'total' => $total_pages,
                    'current' => $current_page
                ));
                ?>
            </div>
        </div>
    </form>
    
    <table class="wp-list-table widefat fixed striped">
        <thead>
            <tr>
                <th>用户</th>
                <th>签到日期</th>
                <th>签到时间</th>
                <th>连续天数</th>
                <th>获得积分</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <?php if (empty($records)): ?>
            <tr>
                <td colspan="6" style="text-align: center;">暂无签到记录</td>
            </tr>
            <?php else: ?>
            <?php foreach ($records as $record): ?>
            <tr>
                <td>
                    <strong><?php echo esc_html($record->display_name); ?></strong><br>
                    <small><?php echo esc_html($record->user_login); ?></small>
                </td>
                <td><?php echo esc_html($record->signin_date); ?></td>
                <td><?php echo esc_html($record->signin_time); ?></td>
                <td><?php echo esc_html($record->continuous_days); ?></td>
                <td><?php echo esc_html($record->points_earned); ?></td>
                <td>
                    <button class="button button-small" 
                            onclick="deleteSigninRecord(<?php echo $record->id; ?
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5234.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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