文章目录[隐藏]
WordPress文创IP柔性二创授权管理插件开发教程
一、项目概述与需求分析
在文创产业快速发展的今天,IP授权管理成为内容创作者面临的重要挑战。本教程将指导您开发一个WordPress插件,帮助文创IP持有者实现灵活的二次创作授权管理。
核心功能需求:
- IP授权规则配置系统
- 二创申请与审核流程
- 授权证书生成与管理
- 使用情况追踪与统计
- 自动化授权协议生成
二、开发环境搭建与插件基础结构
首先,我们需要创建插件的基本文件结构:
<?php
/**
* Plugin Name: 文创IP柔性授权管理系统
* Plugin URI: https://yourwebsite.com/
* Description: 为文创IP提供灵活的二次创作授权管理解决方案
* Version: 1.0.0
* Author: 您的名称
* License: GPL v2 or later
* Text Domain: ip-license-manager
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('IPLM_VERSION', '1.0.0');
define('IPLM_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('IPLM_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
add_action('plugins_loaded', 'iplm_init_plugin');
function iplm_init_plugin() {
// 检查必要依赖
if (!function_exists('get_plugins')) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// 加载文本域
load_plugin_textdomain('ip-license-manager', false, dirname(plugin_basename(__FILE__)) . '/languages');
// 初始化核心类
require_once IPLM_PLUGIN_DIR . 'includes/class-core.php';
$iplm_core = new IPLM_Core();
}
三、数据库设计与数据模型
创建自定义数据库表来存储授权相关数据:
<?php
// 文件路径: includes/class-database.php
class IPLM_Database {
public function __construct() {
register_activation_hook(__FILE__, array($this, 'create_tables'));
}
/**
* 创建插件所需的数据库表
*/
public function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// 授权规则表
$table_rules = $wpdb->prefix . 'iplm_license_rules';
$sql_rules = "CREATE TABLE IF NOT EXISTS $table_rules (
id mediumint(9) NOT NULL AUTO_INCREMENT,
ip_name varchar(200) NOT NULL,
license_type varchar(50) NOT NULL,
allowed_uses text,
restrictions text,
commercial_allowed tinyint(1) DEFAULT 0,
fee_structure text,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
// 授权申请记录表
$table_applications = $wpdb->prefix . 'iplm_applications';
$sql_applications = "CREATE TABLE IF NOT EXISTS $table_applications (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
rule_id mediumint(9) NOT NULL,
project_description text NOT NULL,
intended_use text NOT NULL,
status varchar(20) DEFAULT 'pending',
admin_notes text,
license_key varchar(100),
certificate_data text,
approved_at datetime,
expires_at datetime,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id),
KEY rule_id (rule_id),
KEY license_key (license_key)
) $charset_collate;";
// 使用记录表
$table_usage = $wpdb->prefix . 'iplm_usage_logs';
$sql_usage = "CREATE TABLE IF NOT EXISTS $table_usage (
id mediumint(9) NOT NULL AUTO_INCREMENT,
application_id mediumint(9) NOT NULL,
usage_type varchar(50),
usage_details text,
recorded_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY application_id (application_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql_rules);
dbDelta($sql_applications);
dbDelta($sql_usage);
}
/**
* 插入新的授权规则
* @param array $data 规则数据
* @return int|false 插入ID或失败
*/
public function insert_license_rule($data) {
global $wpdb;
$table = $wpdb->prefix . 'iplm_license_rules';
$defaults = array(
'ip_name' => '',
'license_type' => 'standard',
'allowed_uses' => json_encode(array('digital', 'print')),
'restrictions' => json_encode(array()),
'commercial_allowed' => 0,
'fee_structure' => json_encode(array('base_fee' => 0))
);
$data = wp_parse_args($data, $defaults);
$result = $wpdb->insert($table, $data);
if ($result) {
return $wpdb->insert_id;
}
return false;
}
}
四、授权规则管理模块
创建管理界面让IP持有者配置授权规则:
<?php
// 文件路径: admin/class-rule-manager.php
class IPLM_Rule_Manager {
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
}
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_menu_page(
'IP授权管理',
'IP授权管理',
'manage_options',
'iplm-dashboard',
array($this, 'render_dashboard'),
'dashicons-media-document',
30
);
add_submenu_page(
'iplm-dashboard',
'授权规则',
'授权规则',
'manage_options',
'iplm-rules',
array($this, 'render_rules_page')
);
}
/**
* 加载管理端脚本和样式
*/
public function enqueue_admin_scripts($hook) {
if (strpos($hook, 'iplm-') === false) {
return;
}
wp_enqueue_style(
'iplm-admin-style',
IPLM_PLUGIN_URL . 'assets/css/admin.css',
array(),
IPLM_VERSION
);
wp_enqueue_script(
'iplm-admin-script',
IPLM_PLUGIN_URL . 'assets/js/admin.js',
array('jquery', 'wp-util'),
IPLM_VERSION,
true
);
wp_localize_script('iplm-admin-script', 'iplm_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('iplm_ajax_nonce')
));
}
/**
* 渲染规则管理页面
*/
public function render_rules_page() {
global $wpdb;
// 处理表单提交
if (isset($_POST['submit_rule']) && check_admin_referer('iplm_save_rule')) {
$this->save_license_rule($_POST);
}
// 获取现有规则
$table = $wpdb->prefix . 'iplm_license_rules';
$rules = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC");
?>
<div class="wrap iplm-admin-wrap">
<h1>文创IP授权规则管理</h1>
<div class="iplm-admin-container">
<!-- 添加新规则表单 -->
<div class="iplm-card">
<h2>添加新授权规则</h2>
<form method="post" action="">
<?php wp_nonce_field('iplm_save_rule'); ?>
<table class="form-table">
<tr>
<th><label for="ip_name">IP名称</label></th>
<td>
<input type="text" id="ip_name" name="ip_name"
class="regular-text" required>
<p class="description">请输入文创IP的名称</p>
</td>
</tr>
<tr>
<th><label for="license_type">授权类型</label></th>
<td>
<select id="license_type" name="license_type" required>
<option value="free">免费授权</option>
<option value="standard">标准授权</option>
<option value="premium">高级授权</option>
<option value="custom">自定义授权</option>
</select>
</td>
</tr>
<tr>
<th><label>允许的使用方式</label></th>
<td>
<label><input type="checkbox" name="allowed_uses[]" value="digital" checked> 数字媒体</label><br>
<label><input type="checkbox" name="allowed_uses[]" value="print"> 印刷品</label><br>
<label><input type="checkbox" name="allowed_uses[]" value="merchandise"> 周边商品</label><br>
<label><input type="checkbox" name="allowed_uses[]" value="video"> 视频内容</label>
</td>
</tr>
<tr>
<th><label for="commercial_allowed">允许商业用途</label></th>
<td>
<input type="checkbox" id="commercial_allowed" name="commercial_allowed" value="1">
<label for="commercial_allowed">允许二次创作者进行商业使用</label>
</td>
</tr>
<tr>
<th><label for="fee_structure">费用结构</label></th>
<td>
<textarea id="fee_structure" name="fee_structure"
rows="4" class="large-text">
</textarea>
<p class="description">JSON格式的费用结构,例如:{"base_fee": 100, "revenue_share": 10}</p>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="submit_rule"
class="button button-primary" value="保存规则">
</p>
</form>
</div>
<!-- 现有规则列表 -->
<div class="iplm-card">
<h2>现有授权规则</h2>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>ID</th>
<th>IP名称</th>
<th>授权类型</th>
<th>商业用途</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php if (empty($rules)): ?>
<tr>
<td colspan="6">暂无授权规则</td>
</tr>
<?php else: ?>
<?php foreach ($rules as $rule): ?>
<tr>
<td><?php echo esc_html($rule->id); ?></td>
<td><?php echo esc_html($rule->ip_name); ?></td>
<td><?php echo esc_html($rule->license_type); ?></td>
<td><?php echo $rule->commercial_allowed ? '允许' : '禁止'; ?></td>
<td><?php echo date('Y-m-d H:i', strtotime($rule->created_at)); ?></td>
<td>
<a href="#" class="button button-small view-rule"
data-id="<?php echo $rule->id; ?>">查看</a>
<a href="#" class="button button-small delete-rule"
data-id="<?php echo $rule->id; ?>">删除</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php
}
/**
* 保存授权规则
*/
private function save_license_rule($data) {
global $wpdb;
$allowed_uses = isset($data['allowed_uses']) ? $data['allowed_uses'] : array();
$restrictions = isset($data['restrictions']) ? $data['restrictions'] : array();
$rule_data = array(
'ip_name' => sanitize_text_field($data['ip_name']),
'license_type' => sanitize_text_field($data['license_type']),
'allowed_uses' => json_encode($allowed_uses),
'restrictions' => json_encode($restrictions),
'commercial_allowed' => isset($data['commercial_allowed']) ? 1 : 0,
'fee_structure' => wp_unslash($data['fee_structure'])
);
$db = new IPLM_Database();
$result = $db->insert_license_rule($rule_data);
if ($result) {
echo '<div class="notice notice-success"><p>授权规则保存成功!</p></div>';
} else {
echo '<div class="notice notice-error"><p>保存失败,请重试。</p></div>';
}
}
}
五、前端申请表单与用户界面
创建用户申请授权的前端界面:
<?php
// 文件路径: public/class-application-form.php
class IPLM_Application_Form {
public function __construct() {
add_shortcode('iplm_application_form', array($this, 'render_application_form'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_public_scripts'));
add_action('wp_ajax_iplm_submit_application', array($this, 'handle_application_submission'));
add_action('wp_ajax_nopriv_iplm_submit_application', array($this, 'handle_application_submission'));
}
/**
* 渲染申请表单短代码
*/
public function render_application_form($atts) {
global $wpdb;
// 获取可用的授权规则
$table = $wpdb->prefix . 'iplm_license_rules';
$rules = $wpdb->get_results("SELECT id, ip_name, license_type FROM $table WHERE 1=1");
ob_start();
?>
<div class="iplm-application-form-wrapper">
<h2>文创IP二次创作授权申请</h2>
<?php if (!is_user_logged_in()): ?>
<div class="iplm-notice iplm-notice-warning">
<p>请先<a href="<?php echo wp_login_url(get_permalink()); ?>">登录</a>或<a href="<?php echo wp_registration_url(); ?>">注册</a>后再提交申请。</p>
</div>
<?php else: ?>
<form id="iplm-application-form" method="post">
<div class="iplm-form-group">
<label for="iplm_rule_id">选择IP授权规则 *</label>
<select id="iplm_rule_id" name="rule_id" required>
<option value="">请选择...</option>
<?php foreach ($rules as $rule): ?>
<option value="<?php echo esc_attr($rule->id); ?>">
<?php echo esc_html($rule->ip_name); ?> - <?php echo esc_html($rule->license_type); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="iplm-form-group">
<label for="iplm_project_description">项目描述 *</label>
<textarea id="iplm_project_description" name="project_description"
rows="4" required placeholder="请详细描述您的二次创作项目..."></textarea>
</div>
<div class="iplm-form-group">
<label for="iplm_intended_use">预期用途 *</label>
<textarea id="iplm_intended_use" name="intended_use"
rows="3" required placeholder="请说明您计划如何使用该IP..."></textarea>
</div>
<div class="iplm-form-group">
<label for="iplm_contact_email">联系邮箱 *</label>
<input type="email" id="iplm_contact_email" name="contact_email"
required value="<?php echo esc_attr(wp_get_current_user()->user_email); ?>">
</div>
<div class="iplm-form-group">
<label>
<input type="checkbox" name="agree_terms" required>
我同意并接受 <a href="#" target="_blank">授权协议条款</a> *
</label>
</div>
<input type="hidden" name="action" value="iplm_submit_application">
<?php wp_nonce_field('iplm_application_nonce', 'iplm_nonce'); ?>
<div class="iplm-form-submit">
<button type="submit" class="iplm-submit-btn">
<span class="btn-text">提交申请</span>
<span class="loading-spinner" style="display:none;">处理中...</span>
</button>
</div>
<div id="iplm-form-message" class="iplm-form-message" style="display:none;"></div>
</form>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('#iplm-application-form').on('submit', function(e) {
e.preventDefault();
var $form = $(this);
接上文:
var $submitBtn = $form.find('.iplm-submit-btn');
var $btnText = $submitBtn.find('.btn-text');
var $spinner = $submitBtn.find('.loading-spinner');
var $message = $('#iplm-form-message');
// 显示加载状态
$btnText.hide();
$spinner.show();
$message.hide().removeClass('success error');
// 收集表单数据
var formData = $form.serialize();
// 发送AJAX请求
$.ajax({
url: iplm_ajax.ajax_url,
type: 'POST',
data: formData,
dataType: 'json',
success: function(response) {
if (response.success) {
$message.addClass('success').html(response.data.message).show();
$form[0].reset(); // 重置表单
} else {
$message.addClass('error').html(response.data.message).show();
}
},
error: function() {
$message.addClass('error').html('提交失败,请稍后重试。').show();
},
complete: function() {
$btnText.show();
$spinner.hide();
}
});
});
});
</script>
<?php endif; ?>
</div>
<?php
return ob_get_clean();
}
/**
* 处理申请提交
*/
public function handle_application_submission() {
// 验证nonce
if (!check_ajax_referer('iplm_application_nonce', 'iplm_nonce', false)) {
wp_send_json_error(array('message' => '安全验证失败,请刷新页面重试。'));
}
// 验证用户登录状态
if (!is_user_logged_in()) {
wp_send_json_error(array('message' => '请先登录后再提交申请。'));
}
// 验证必填字段
$required_fields = array('rule_id', 'project_description', 'intended_use', 'contact_email');
foreach ($required_fields as $field) {
if (empty($_POST[$field])) {
wp_send_json_error(array('message' => '请填写所有必填字段。'));
}
}
// 验证邮箱格式
if (!is_email($_POST['contact_email'])) {
wp_send_json_error(array('message' => '请输入有效的邮箱地址。'));
}
global $wpdb;
// 生成唯一的授权密钥
$license_key = 'IPLM-' . strtoupper(wp_generate_password(12, false)) . '-' . time();
// 准备申请数据
$application_data = array(
'user_id' => get_current_user_id(),
'rule_id' => intval($_POST['rule_id']),
'project_description' => sanitize_textarea_field($_POST['project_description']),
'intended_use' => sanitize_textarea_field($_POST['intended_use']),
'status' => 'pending',
'license_key' => $license_key,
'created_at' => current_time('mysql')
);
// 插入数据库
$table = $wpdb->prefix . 'iplm_applications';
$result = $wpdb->insert($table, $application_data);
if ($result) {
// 发送通知邮件
$this->send_notification_email($application_data);
wp_send_json_success(array(
'message' => '申请提交成功!您的申请编号为:' . $license_key . ',我们将在3个工作日内处理您的申请。'
));
} else {
wp_send_json_error(array('message' => '提交失败,请稍后重试。'));
}
}
/**
* 发送通知邮件
*/
private function send_notification_email($application_data) {
$user = wp_get_current_user();
$admin_email = get_option('admin_email');
$subject = '新的文创IP授权申请 - ' . $application_data['license_key'];
$message = "新的授权申请详情:nn";
$message .= "申请用户:" . $user->display_name . " (" . $user->user_email . ")n";
$message .= "申请编号:" . $application_data['license_key'] . "n";
$message .= "申请时间:" . $application_data['created_at'] . "n";
$message .= "项目描述:" . $application_data['project_description'] . "n";
$message .= "预期用途:" . $application_data['intended_use'] . "nn";
$message .= "请登录管理后台处理此申请。";
wp_mail($admin_email, $subject, $message);
}
}
六、授权证书生成模块
<?php
// 文件路径: includes/class-certificate-generator.php
class IPLM_Certificate_Generator {
/**
* 生成授权证书PDF
* @param int $application_id 申请ID
* @return string PDF文件路径
*/
public function generate_certificate_pdf($application_id) {
global $wpdb;
// 获取申请详情
$applications_table = $wpdb->prefix . 'iplm_applications';
$rules_table = $wpdb->prefix . 'iplm_license_rules';
$query = $wpdb->prepare(
"SELECT a.*, r.ip_name, r.license_type, r.allowed_uses
FROM $applications_table a
LEFT JOIN $rules_table r ON a.rule_id = r.id
WHERE a.id = %d",
$application_id
);
$application = $wpdb->get_row($query);
if (!$application) {
return false;
}
// 获取用户信息
$user = get_userdata($application->user_id);
// 创建证书HTML
$html = $this->get_certificate_html($application, $user);
// 生成PDF文件
$filename = 'certificate-' . $application->license_key . '.pdf';
$filepath = IPLM_PLUGIN_DIR . 'certificates/' . $filename;
// 确保目录存在
wp_mkdir_p(dirname($filepath));
// 使用TCPDF生成PDF(需要先安装TCPDF库)
require_once IPLM_PLUGIN_DIR . 'vendor/tecnickcom/tcpdf/tcpdf.php';
$pdf = new TCPDF('L', 'mm', 'A4', true, 'UTF-8', false);
// 设置文档信息
$pdf->SetCreator('WordPress IP License Manager');
$pdf->SetAuthor(get_bloginfo('name'));
$pdf->SetTitle('授权证书 - ' . $application->license_key);
// 移除默认页眉页脚
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
// 添加页面
$pdf->AddPage();
// 设置字体
$pdf->SetFont('stsongstdlight', '', 14);
// 写入HTML内容
$pdf->writeHTML($html, true, false, true, false, '');
// 保存文件
$pdf->Output($filepath, 'F');
// 更新数据库记录
$wpdb->update(
$applications_table,
array('certificate_data' => json_encode(array('filepath' => $filepath))),
array('id' => $application_id)
);
return $filepath;
}
/**
* 生成证书HTML
*/
private function get_certificate_html($application, $user) {
$allowed_uses = json_decode($application->allowed_uses, true);
$allowed_uses_text = is_array($allowed_uses) ? implode('、', $allowed_uses) : '';
$html = '
<style>
.certificate {
border: 20px solid #f0e6d2;
padding: 40px;
background: linear-gradient(to bottom, #fffef0, #fff8e1);
font-family: "Microsoft YaHei", "SimSun", serif;
}
.header {
text-align: center;
margin-bottom: 40px;
}
.title {
font-size: 36px;
color: #b8860b;
font-weight: bold;
margin-bottom: 10px;
}
.subtitle {
font-size: 18px;
color: #666;
margin-bottom: 30px;
}
.content {
font-size: 16px;
line-height: 1.8;
margin-bottom: 30px;
}
.details {
border-top: 2px solid #b8860b;
padding-top: 20px;
margin-top: 30px;
}
.footer {
text-align: center;
margin-top: 50px;
font-size: 14px;
color: #888;
}
.signature {
margin-top: 60px;
text-align: right;
}
</style>
<div class="certificate">
<div class="header">
<div class="title">文创IP二次创作授权证书</div>
<div class="subtitle">Certificate of Derivative Creation Authorization</div>
</div>
<div class="content">
<p>根据《文创IP柔性授权管理协议》,兹授权:</p>
<p style="text-align: center; font-size: 20px; margin: 20px 0;">
<strong>' . esc_html($user->display_name) . '</strong>
</p>
<p>对以下文创IP进行二次创作:</p>
<p style="text-align: center; font-size: 20px; margin: 20px 0;">
<strong>' . esc_html($application->ip_name) . '</strong>
</p>
<p>授权编号:<strong>' . esc_html($application->license_key) . '</strong></p>
<p>授权类型:<strong>' . esc_html($application->license_type) . '</strong></p>
<p>授权有效期:<strong>' . date('Y年m月d日', strtotime($application->approved_at)) . ' 至 ' .
date('Y年m月d日', strtotime($application->expires_at)) . '</strong></p>
</div>
<div class="details">
<p><strong>授权范围:</strong></p>
<p>允许的使用方式:' . esc_html($allowed_uses_text) . '</p>
<p>商业用途:' . ($application->commercial_allowed ? '允许' : '不允许') . '</p>
<p>项目描述:' . esc_html($application->project_description) . '</p>
</div>
<div class="signature">
<p>授权方:' . get_bloginfo('name') . '</p>
<p>签发日期:' . date('Y年m月d日') . '</p>
</div>
<div class="footer">
<p>本证书最终解释权归授权方所有</p>
<p>验证网址:' . home_url('/verify?key=' . $application->license_key) . '</p>
</div>
</div>';
return $html;
}
/**
* 验证授权证书
*/
public function verify_certificate($license_key) {
global $wpdb;
$table = $wpdb->prefix . 'iplm_applications';
$query = $wpdb->prepare(
"SELECT a.*, r.ip_name, u.display_name
FROM $table a
LEFT JOIN {$wpdb->prefix}iplm_license_rules r ON a.rule_id = r.id
LEFT JOIN {$wpdb->users} u ON a.user_id = u.ID
WHERE a.license_key = %s AND a.status = 'approved'",
$license_key
);
$certificate = $wpdb->get_row($query);
if (!$certificate) {
return false;
}
// 检查是否过期
if (strtotime($certificate->expires_at) < current_time('timestamp')) {
return array('valid' => false, 'reason' => '证书已过期');
}
return array(
'valid' => true,
'data' => $certificate
);
}
}
七、使用统计与数据分析
<?php
// 文件路径: includes/class-analytics.php
class IPLM_Analytics {
/**
* 获取授权统计概览
*/
public function get_license_overview() {
global $wpdb;
$applications_table = $wpdb->prefix . 'iplm_applications';
$rules_table = $wpdb->prefix . 'iplm_license_rules';
$stats = array(
'total_applications' => 0,
'pending_applications' => 0,
'approved_applications' => 0,
'rejected_applications' => 0,
'popular_ips' => array(),
'monthly_trend' => array()
);
// 获取申请总数
$stats['total_applications'] = $wpdb->get_var(
"SELECT COUNT(*) FROM $applications_table"
);
// 按状态统计
$status_counts = $wpdb->get_results(
"SELECT status, COUNT(*) as count
FROM $applications_table
GROUP BY status"
);
foreach ($status_counts as $row) {
if ($row->status == 'pending') {
$stats['pending_applications'] = $row->count;
} elseif ($row->status == 'approved') {
$stats['approved_applications'] = $row->count;
} elseif ($row->status == 'rejected') {
$stats['rejected_applications'] = $row->count;
}
}
// 获取热门IP
$stats['popular_ips'] = $wpdb->get_results(
"SELECT r.ip_name, COUNT(a.id) as application_count
FROM $applications_table a
LEFT JOIN $rules_table r ON a.rule_id = r.id
GROUP BY r.ip_name
ORDER BY application_count DESC
LIMIT 5"
);
// 获取月度趋势
$stats['monthly_trend'] = $wpdb->get_results(
"SELECT DATE_FORMAT(created_at, '%Y-%m') as month,
COUNT(*) as count,
SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END) as approved_count
FROM $applications_table
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 6 MONTH)
GROUP BY DATE_FORMAT(created_at, '%Y-%m')
ORDER BY month DESC"
);
return $stats;
}
/**
* 生成统计报告HTML
*/
public function generate_report_html() {
$stats = $this->get_license_overview();
ob_start();
?>
<div class="iplm-analytics-dashboard">
<h2>授权统计概览</h2>
<div class="iplm-stats-grid">
<div class="iplm-stat-card">
<h3>总申请数</h3>
<div class="stat-number"><?php echo $stats['total_applications']; ?></div>
</div>
<div class="iplm-stat-card">
<h3>待处理</h3>
<div class="stat-number"><?php echo $stats['pending_applications']; ?></div>
</div>
<div class="iplm-stat-card">
<h3>已批准</h3>
<div class="stat-number"><?php echo $stats['approved_applications']; ?></div>
</div>
<div class="iplm-stat-card">
<h3>已拒绝</h3>
<div class="stat-number"><?php echo $stats['rejected_applications']; ?></div>
</div>
</div>
<div class="iplm-charts-section">
<div class="iplm-chart-card">
<h3>热门IP排行</h3>
<table class="wp-list-table widefat fixed">
<thead>
<tr>
<th>IP名称</th>
<th>申请数量</th>
</tr>
</thead>
<tbody>
<?php foreach ($stats['popular_ips'] as $ip): ?>
<tr>
<td><?php echo esc_html($ip->ip_name); ?></td>
<td><?php echo $ip->application_count; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="iplm-chart-card">
<h3>月度申请趋势</h3>
<table class="wp-list-table widefat fixed">
<thead>
<tr>
<th>月份</th>
<th>总申请</th>
<th>批准数量</th>
<th>批准率</th>
</tr>
</thead>
<tbody>
<?php foreach ($stats['monthly_trend'] as $month): ?>
<tr>
<td><?php echo esc_html($month->month); ?></td>
<td><?php echo $month->count; ?></td>
<td><?php echo $month->approved_count; ?></td>
<td><?php echo $month->count > 0 ?
round(($month->approved_count / $month->count) * 100, 1) . '%' : '0%'; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php
