| Server IP : 43.141.49.107 / Your IP : 113.219.202.44 Web Server : Apache System : Linux VM-8-5-opencloudos 6.6.34-9.oc9.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jun 19 19:35:45 CST 2024 x86_64 User : www ( 1000) PHP Version : 8.1.27 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /www/wwwroot/www.ucppt.com/wp-content/plugins/wpcom-member-pro/includes/ |
Upload File : |
<?php
namespace WPCOM\Member;
defined('ABSPATH') || exit;
class Overview{
function __construct() {
add_action('admin_menu', [$this, 'admin_menu'], 999);
add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
add_action('wpcom_member_data_overview', [$this, 'details_item']);
add_action('wpcom_member_data_overview', [$this, 'users_chart']);
add_action('wpcom_member_data_overview', [$this, 'orders_chart']);
add_action('wp_ajax_wpcom_users_chart', [$this, 'users_chart_data']);
add_action('wp_ajax_wpcom_orders_chart', [$this, 'orders_chart_data']);
}
function admin_menu(){
global $submenu;
add_submenu_page('wpcom-member-pro', '数据概览', '数据概览', 'manage_options', 'wpcom-member-data', function(){ ?>
<div class="wrap">
<h1>数据概览</h1>
<p class="wpcom-member-data-subtitle">温馨提示:基于性能考量以下数据可能会有10分钟的缓存期</p>
<div class="wpcom-member-data-overview">
<?php do_action('wpcom_member_data_overview'); ?>
</div>
</div>
<?php }, 1);
if($submenu && isset($submenu['wpcom-member-pro'])){
$first = array_shift($submenu['wpcom-member-pro']);
$first[0] = '设置选项';
$submenu['wpcom-member-pro'][] = $first;
}
}
function enqueue_scripts(){
global $pagenow;
if($pagenow !== 'admin.php' || !isset($_GET['page']) || $_GET['page'] !== 'wpcom-member-data') return;
wp_enqueue_script('chart', WPCOM_MP_URI . 'js/chart.js', [], WPCOM_MP_VERSION, true);
wp_enqueue_script('overview', WPCOM_MP_URI . 'js/overview.js', ['chart'], WPCOM_MP_VERSION, true);
}
function details_item() { ?>
<div class="overview-widget overview-widget-users">
<h2 class="overview-widget-title">用户</h2>
<p class="overview-widget-desc">用户注册数据</p>
<p><span>今日注册:</span><?php echo $this->get_total_users('today'); ?></p>
<p><span>本月注册:</span><?php echo $this->get_total_users('month'); ?></p>
<p><span>今年注册:</span><?php echo $this->get_total_users('year'); ?></p>
<p><span>总用户数:</span><?php echo $this->get_total_users(); ?></p>
</div>
<?php if(!empty(VIP::get_vip_types())){ ?>
<div class="overview-widget overview-widget-vip">
<h2 class="overview-widget-title">会员</h2>
<p class="overview-widget-desc">会员数据为开通会员数,不包含已有会员续费、和升级</p>
<p><span>今日开通:</span><?php echo VIP::get_total_vip('today'); ?></p>
<p><span>本月开通:</span><?php echo VIP::get_total_vip('month'); ?></p>
<p><span>今年开通:</span><?php echo VIP::get_total_vip('year'); ?></p>
<p><span>总会员数:</span><?php $total = VIP::get_total_vip(); echo $total['active'] . ' / ' . $total['total']; ?>(有效期内 / 总开通)</p>
</div>
<?php } ?>
<div class="overview-widget overview-widget-orders">
<h2 class="overview-widget-title">订单</h2>
<p class="overview-widget-desc">以下数据不统计积分支付订单</p>
<p><span>今日订单:</span><?php echo Order::get_order_count('today'); ?></p>
<p><span>本月订单:</span><?php echo Order::get_order_count('month'); ?></p>
<p><span>今年订单:</span><?php echo Order::get_order_count('year'); ?></p>
<p><span>总订单数:</span><?php echo Order::get_order_count(); ?></p>
</div>
<div class="overview-widget overview-widget-income">
<h2 class="overview-widget-title">收入(元)</h2>
<p class="overview-widget-desc">余额涉及消费、充值、兑换、线下转账等多种情况,所以针对余额收入仅统计在线充值方式,代金券充值、余额消费等不统计</p>
<p><span>今日收入:</span><?php echo Order::get_order_income('today'); ?></p>
<p><span>本月收入:</span><?php echo Order::get_order_income('month'); ?></p>
<p><span>今年收入:</span><?php echo Order::get_order_income('year'); ?></p>
<p><span>总收入:</span><?php echo Order::get_order_income(); ?></p>
</div>
<?php
}
function users_chart(){
?>
<div class="overview-widget overview-widget2 overview-widget-users-chart">
<h2 class="overview-widget-title">近一年用户数据</h2>
<div class="chart-container">
<div class="chart-loading">数据加载中...</div>
<canvas id="usersChart" class="overview-widget-chart"></canvas>
</div>
</div>
<?php
}
function users_chart_data(){
if(current_user_can('manage_options')){
$start = date('Y-m-d', strtotime('-1 year'));
$end = current_time('Y-m-d');
wp_send_json_success($this->get_user_vip_stats($start, $end));
}else{
wp_send_json_error(['message' => 'Permission denied']);
}
}
function orders_chart(){
?>
<div class="overview-widget overview-widget2 overview-widget-orders-chart">
<h2 class="overview-widget-title">近一年订单数据</h2>
<div class="chart-container">
<div class="chart-loading">数据加载中...</div>
<canvas id="ordersChart" class="overview-widget-chart"></canvas>
</div>
</div>
<?php
}
function orders_chart_data() {
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'Permission denied']);
}
global $wpdb;
$start = date('Y-m-d', strtotime('-1 year'));
$end = current_time('Y-m-d');
$cache_key = 'wpcom_order_stats_' . substr(md5(serialize([$start, $end])), 0, 12);
$cached = get_transient($cache_key);
if ($cached !== false) {
return wp_send_json_success($cached);
}
$order_table = $wpdb->order_table;
// 初始化日期数组
$start_date = new \DateTime($start);
$end_date = new \DateTime($end);
$period = new \DatePeriod($start_date, new \DateInterval('P1D'), (clone $end_date)->modify('+1 day'));
$result = [];
foreach ($period as $date) {
$d = $date->format('Y-m-d');
$result[$d] = ['date' => $d, 'orders' => 0, 'incomes' => 0];
}
// 查询订单数(排除积分支付)
$orders = $wpdb->get_results(
$wpdb->prepare(
"SELECT DATE(time) as day, COUNT(*) as total
FROM $order_table
WHERE status = 'paid' AND payment_gateway != %s
AND time BETWEEN %s AND %s
GROUP BY day",
'points',
$start . ' 00:00:00',
$end . ' 23:59:59'
),
ARRAY_A
);
foreach ($orders as $row) {
if (isset($result[$row['day']])) {
$result[$row['day']]['orders'] = (int) $row['total'];
}
}
// 查询收入(排除积分+钱包支付)
$incomes = $wpdb->get_results(
$wpdb->prepare(
"SELECT DATE(time) as day, SUM(price) as income
FROM $order_table
WHERE status = 'paid' AND payment_gateway NOT IN (%s, %s)
AND time BETWEEN %s AND %s
GROUP BY day",
'points', 'wallet',
$start . ' 00:00:00',
$end . ' 23:59:59'
),
ARRAY_A
);
foreach ($incomes as $row) {
if (isset($result[$row['day']])) {
$result[$row['day']]['incomes'] = round((float) $row['income'], 2);
}
}
$res = array_values($result);
// 缓存 10 分钟
set_transient($cache_key, $res, MINUTE_IN_SECONDS * 10);
wp_send_json_success($res);
}
function get_total_users($period = 'total', $start = '', $end = '') {
global $wpdb;
$cache_key = 'wpcom_total_users_' . substr(md5(serialize([$period, $start, $end])), 0, 12);
// 尝试从缓存获取
$cached = get_transient($cache_key);
if ($cached !== false) {
return (int)$cached;
}
// 无时间条件,查询全部用户,使用 count_users 函数,已自带缓存
if (!$start && !$end && $period === 'total') {
$count_users = count_users();
$total = $count_users['total_users'];
set_transient($cache_key, $total, 600); // 缓存10分钟
return $total;
}
// 计算时间范围
if (!$start && !$end) {
$today = current_time('Y-m-d');
$month = date_i18n('Y-m');
$year = date_i18n('Y');
if ($period === 'today') {
$start = $today . ' 00:00:00';
$end = $today . ' 23:59:59';
} elseif ($period === 'month') {
$start = $month . '-01 00:00:00';
$end = $today . ' 23:59:59';
} elseif ($period === 'year') {
$start = $year . '-01-01 00:00:00';
$end = $today . ' 23:59:59';
}
} else {
// 补全时间格式(保证有时分秒)
if ($start && strlen($start) === 10) {
$start .= ' 00:00:00';
}
if ($end && strlen($end) === 10) {
$end .= ' 23:59:59';
}
}
// 构造SQL条件
$is_multisite = is_multisite();
$where = [];
if($is_multisite){
$meta_key = $wpdb->get_blog_prefix() . 'capabilities';
$where = [ $wpdb->prepare("m.meta_key = %s", $meta_key) ];
}
$time_key = $is_multisite ? 'u.user_registered' : 'user_registered';
if ($start && $end) {
$where[] = $wpdb->prepare("$time_key BETWEEN %s AND %s", $start, $end);
} elseif ($start) {
$where[] = $wpdb->prepare("$time_key >= %s", $start);
} elseif ($end) {
$where[] = $wpdb->prepare("$time_key <= %s", $end);
}
$sql = "SELECT COUNT(DISTINCT ID) FROM {$wpdb->users}";
if($is_multisite){
$sql = "SELECT COUNT(DISTINCT u.ID) FROM {$wpdb->users} u";
$sql .= " INNER JOIN {$wpdb->usermeta} m ON u.ID = m.user_id";
}
if (!empty($where)) {
$sql .= " WHERE " . implode(' AND ', $where);
}
$total = (int) $wpdb->get_var($sql);
// 设置缓存,缓存10分钟
set_transient($cache_key, $total, 600);
return $total;
}
function get_user_vip_stats($start, $end) {
global $wpdb;
$cache_key = 'wpcom_user_stats_' . substr(md5(serialize([$start, $end])), 0, 12);
$cached = get_transient($cache_key);
if ($cached !== false) {
return $cached;
}
// 初始化每天数据
$start_date = new \DateTime($start);
$end_date = new \DateTime($end);
$period = new \DatePeriod($start_date, new \DateInterval('P1D'), (clone $end_date)->modify('+1 day'));
$is_vip = !empty(VIP::get_vip_types());
$result = [];
foreach ($period as $date) {
$day = $date->format('Y-m-d');
$result[$day] = $is_vip ? ['date' => $day, 'users' => 0, 'vips' => 0] : ['date' => $day, 'users' => 0];
}
// 查询注册用户数量(按天)
$is_multisite = is_multisite();
if($is_multisite) {
$sql = $wpdb->prepare(
"SELECT DATE(u.user_registered) as reg_date, COUNT(DISTINCT u.ID) as total
FROM {$wpdb->users} u
INNER JOIN {$wpdb->usermeta} m ON u.ID = m.user_id
WHERE m.meta_key = %s
AND u.user_registered BETWEEN %s AND %s
GROUP BY reg_date",
$wpdb->get_blog_prefix() . 'capabilities',
$start . ' 00:00:00',
$end . ' 23:59:59'
);
} else {
$sql = $wpdb->prepare(
"SELECT DATE(user_registered) as reg_date, COUNT(DISTINCT ID) as total
FROM {$wpdb->users}
WHERE user_registered BETWEEN %s AND %s
GROUP BY reg_date",
$start . ' 00:00:00',
$end . ' 23:59:59'
);
}
$users = $wpdb->get_results($sql, ARRAY_A);
foreach ($users as $row) {
if (isset($result[$row['reg_date']])) {
$result[$row['reg_date']]['users'] = (int) $row['total'];
}
}
// 查询会员开通数量(按天)
if($is_vip){
$vips = $wpdb->get_results(
$wpdb->prepare(
"SELECT DATE(meta_value) as vip_date, COUNT(*) as total
FROM {$wpdb->usermeta}
WHERE meta_key = %s
AND meta_value BETWEEN %s AND %s
GROUP BY vip_date",
$wpdb->get_blog_prefix() . 'vip_begin_date',
$start . ' 00:00:00',
$end . ' 23:59:59'
),
ARRAY_A
);
foreach ($vips as $row) {
if (isset($result[$row['vip_date']])) {
$result[$row['vip_date']]['vips'] = (int) $row['total'];
}
}
}
$res = array_values($result);
// 设置缓存,缓存10分钟
set_transient($cache_key, $res, 600);
return $res;
}
}
new Overview();