文章目录[隐藏]
实战教程:在WordPress网站中添加在线个人财务记账与预算管理小程序
引言:为什么网站需要个人财务工具?
在当今数字化时代,个人财务管理已成为许多人日常生活中的重要组成部分。随着在线消费、数字支付和远程工作的普及,人们越来越需要便捷的工具来跟踪和管理个人财务。对于网站运营者而言,在网站上集成实用的个人财务工具不仅能增加用户粘性,还能提升网站的价值和实用性。
WordPress作为全球最流行的内容管理系统,其强大的可扩展性使其成为实现此类功能的理想平台。通过代码二次开发,我们可以在WordPress网站上添加一个完整的在线个人财务记账与预算管理小程序,为用户提供实用的互联网小工具。
本教程将详细指导您如何通过WordPress代码二次开发,实现一个功能完整的个人财务管理系统,涵盖记账、预算管理、数据可视化等核心功能。
第一部分:项目规划与环境准备
1.1 功能需求分析
在开始开发之前,我们需要明确个人财务管理系统应包含的核心功能:
- 用户认证与数据隔离:确保每个用户只能访问自己的财务数据
- 收入与支出记录:支持添加、编辑、删除和分类财务记录
- 预算管理:允许用户设置月度/年度预算并跟踪执行情况
- 数据可视化:通过图表展示财务趋势和分类占比
- 数据导出:支持将财务数据导出为CSV或Excel格式
- 报表生成:自动生成月度/年度财务报告
1.2 开发环境搭建
为了进行WordPress二次开发,我们需要准备以下环境:
- 本地开发环境:安装XAMPP、MAMP或Local by Flywheel
- WordPress安装:最新版本的WordPress核心文件
- 代码编辑器:VS Code、Sublime Text或PHPStorm
- 浏览器开发者工具:用于调试前端代码
1.3 创建自定义插件
我们将通过创建自定义插件的方式实现财务管理系统,这样可以确保代码的独立性和可维护性。
在WordPress的wp-content/plugins目录下创建新文件夹personal-finance-manager,并在其中创建主插件文件:
<?php
/**
* Plugin Name: 个人财务记账与预算管理系统
* Plugin URI: https://yourwebsite.com/
* Description: 在WordPress网站中添加在线个人财务记账与预算管理功能
* Version: 1.0.0
* Author: 您的名称
* License: GPL v2 or later
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('PFM_VERSION', '1.0.0');
define('PFM_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('PFM_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
require_once PFM_PLUGIN_DIR . 'includes/class-pfm-init.php';
第二部分:数据库设计与数据模型
2.1 创建自定义数据库表
个人财务数据需要专门的数据库表来存储。我们将在插件激活时创建这些表:
// 在includes/class-pfm-db.php中
class PFM_DB {
public static function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// 财务记录表
$table_name = $wpdb->prefix . 'pfm_transactions';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
type varchar(20) NOT NULL COMMENT 'income/expense',
category varchar(100) NOT NULL,
amount decimal(10,2) NOT NULL,
description text,
transaction_date date NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id),
KEY transaction_date (transaction_date),
KEY category (category)
) $charset_collate;";
// 预算表
$budget_table = $wpdb->prefix . 'pfm_budgets';
$budget_sql = "CREATE TABLE IF NOT EXISTS $budget_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
category varchar(100) NOT NULL,
budget_amount decimal(10,2) NOT NULL,
period varchar(20) NOT NULL COMMENT 'monthly/yearly',
start_date date NOT NULL,
end_date date,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id),
KEY period (period)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
dbDelta($budget_sql);
}
}
2.2 数据模型类
创建数据模型类来处理财务数据的CRUD操作:
// 在includes/class-pfm-transaction.php中
class PFM_Transaction {
private $db;
private $table_name;
public function __construct() {
global $wpdb;
$this->db = $wpdb;
$this->table_name = $wpdb->prefix . 'pfm_transactions';
}
// 添加财务记录
public function add($user_id, $data) {
$defaults = array(
'type' => 'expense',
'category' => '其他',
'amount' => 0.00,
'description' => '',
'transaction_date' => current_time('Y-m-d')
);
$data = wp_parse_args($data, $defaults);
return $this->db->insert(
$this->table_name,
array(
'user_id' => $user_id,
'type' => sanitize_text_field($data['type']),
'category' => sanitize_text_field($data['category']),
'amount' => floatval($data['amount']),
'description' => sanitize_textarea_field($data['description']),
'transaction_date' => sanitize_text_field($data['transaction_date'])
),
array('%d', '%s', '%s', '%f', '%s', '%s')
);
}
// 获取用户的财务记录
public function get_user_transactions($user_id, $filters = array()) {
$where = array('user_id = %d');
$params = array($user_id);
if (!empty($filters['type'])) {
$where[] = 'type = %s';
$params[] = $filters['type'];
}
if (!empty($filters['category'])) {
$where[] = 'category = %s';
$params[] = $filters['category'];
}
if (!empty($filters['start_date'])) {
$where[] = 'transaction_date >= %s';
$params[] = $filters['start_date'];
}
if (!empty($filters['end_date'])) {
$where[] = 'transaction_date <= %s';
$params[] = $filters['end_date'];
}
$where_clause = implode(' AND ', $where);
$sql = $this->db->prepare(
"SELECT * FROM {$this->table_name} WHERE {$where_clause} ORDER BY transaction_date DESC",
$params
);
return $this->db->get_results($sql);
}
// 更多方法:更新、删除、统计等
}
第三部分:用户界面与前端开发
3.1 创建管理页面
在WordPress后台添加财务管理菜单项:
// 在includes/class-pfm-admin.php中
class PFM_Admin {
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(
'个人财务管理',
'财务记账',
'read', // 所有登录用户都可以访问
'personal-finance',
array($this, 'render_dashboard'),
'dashicons-chart-area',
30
);
add_submenu_page(
'personal-finance',
'财务概览',
'概览',
'read',
'personal-finance',
array($this, 'render_dashboard')
);
add_submenu_page(
'personal-finance',
'添加记录',
'添加记录',
'read',
'pfm-add-transaction',
array($this, 'render_add_transaction_page')
);
add_submenu_page(
'personal-finance',
'预算管理',
'预算管理',
'read',
'pfm-budgets',
array($this, 'render_budgets_page')
);
add_submenu_page(
'personal-finance',
'财务报告',
'报告',
'read',
'pfm-reports',
array($this, 'render_reports_page')
);
}
public function render_dashboard() {
include PFM_PLUGIN_DIR . 'templates/dashboard.php';
}
// 其他页面渲染方法
}
3.2 前端模板设计
创建财务概览页面模板:
<!-- 在templates/dashboard.php中 -->
<div class="wrap pfm-dashboard">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<div class="pfm-stats-container">
<div class="pfm-stat-card">
<h3>本月收入</h3>
<div class="pfm-stat-amount income">¥<?php echo number_format($monthly_income, 2); ?></div>
</div>
<div class="pfm-stat-card">
<h3>本月支出</h3>
<div class="pfm-stat-amount expense">¥<?php echo number_format($monthly_expense, 2); ?></div>
</div>
<div class="pfm-stat-card">
<h3>本月结余</h3>
<div class="pfm-stat-amount balance">¥<?php echo number_format($monthly_balance, 2); ?></div>
</div>
<div class="pfm-stat-card">
<h3>预算执行率</h3>
<div class="pfm-stat-amount"><?php echo $budget_usage; ?>%</div>
</div>
</div>
<div class="pfm-chart-container">
<h2>月度收支趋势</h2>
<canvas id="pfm-monthly-trend-chart" width="400" height="200"></canvas>
</div>
<div class="pfm-recent-transactions">
<h2>最近交易记录</h2>
<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 foreach($recent_transactions as $transaction): ?>
<tr>
<td><?php echo esc_html($transaction->transaction_date); ?></td>
<td><?php echo esc_html($transaction->category); ?></td>
<td>
<span class="pfm-type-badge <?php echo $transaction->type; ?>">
<?php echo $transaction->type == 'income' ? '收入' : '支出'; ?>
</span>
</td>
<td><?php echo esc_html($transaction->description); ?></td>
<td class="amount <?php echo $transaction->type; ?>">
<?php echo ($transaction->type == 'income' ? '+' : '-') . number_format($transaction->amount, 2); ?>
</td>
<td>
<button class="button button-small edit-transaction" data-id="<?php echo $transaction->id; ?>">编辑</button>
<button class="button button-small delete-transaction" data-id="<?php echo $transaction->id; ?>">删除</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
3.3 添加记录表单
创建添加财务记录的表单界面:
<!-- 在templates/add-transaction.php中 -->
<div class="wrap pfm-add-transaction">
<h1>添加财务记录</h1>
<form id="pfm-transaction-form" method="post">
<?php wp_nonce_field('pfm_add_transaction', 'pfm_nonce'); ?>
<div class="pfm-form-section">
<h2>基本信息</h2>
<div class="pfm-form-row">
<label for="transaction-type">类型</label>
<select id="transaction-type" name="type" required>
<option value="income">收入</option>
<option value="expense" selected>支出</option>
</select>
</div>
<div class="pfm-form-row">
<label for="transaction-category">类别</label>
<select id="transaction-category" name="category" required>
<option value="餐饮">餐饮</option>
<option value="交通">交通</option>
<option value="购物">购物</option>
<option value="娱乐">娱乐</option>
<option value="住房">住房</option>
<option value="医疗">医疗</option>
<option value="教育">教育</option>
<option value="投资">投资</option>
<option value="工资收入">工资收入</option>
<option value="其他收入">其他收入</option>
<option value="其他">其他</option>
</select>
<input type="text" id="new-category" name="new_category" placeholder="或输入新类别" style="display:none;">
<button type="button" id="add-category-btn" class="button">+</button>
</div>
<div class="pfm-form-row">
<label for="transaction-amount">金额 (¥)</label>
<input type="number" id="transaction-amount" name="amount" step="0.01" min="0" required>
</div>
<div class="pfm-form-row">
<label for="transaction-date">日期</label>
<input type="date" id="transaction-date" name="transaction_date" value="<?php echo date('Y-m-d'); ?>" required>
</div>
</div>
<div class="pfm-form-section">
<h2>详细信息</h2>
<div class="pfm-form-row">
<label for="transaction-description">描述</label>
<textarea id="transaction-description" name="description" rows="3" placeholder="可选的描述信息..."></textarea>
</div>
<div class="pfm-form-row">
<label for="transaction-tags">标签</label>
<input type="text" id="transaction-tags" name="tags" placeholder="用逗号分隔标签">
</div>
</div>
<div class="pfm-form-actions">
<button type="submit" class="button button-primary">保存记录</button>
<button type="button" id="save-and-add-another" class="button">保存并继续添加</button>
<a href="<?php echo admin_url('admin.php?page=personal-finance'); ?>" class="button">返回概览</a>
</div>
</form>
</div>
第四部分:预算管理功能实现
4.1 预算数据模型
创建预算管理的数据模型类:
// 在includes/class-pfm-budget.php中
class PFM_Budget {
private $db;
private $table_name;
public function __construct() {
global $wpdb;
$this->db = $wpdb;
$this->table_name = $wpdb->prefix . 'pfm_budgets';
}
// 设置预算
public function set_budget($user_id, $data) {
$defaults = array(
'category' => '',
'budget_amount' => 0.00,
'period' => 'monthly',
'start_date' => date('Y-m-01'), // 当月第一天
'end_date' => null
);
$data = wp_parse_args($data, $defaults);
// 检查是否已存在该类别同期的预算
$existing = $this->db->get_var($this->db->prepare(
"SELECT id FROM {$this->table_name}
WHERE user_id = %d AND category = %s AND period = %s
AND start_date = %s",
$user_id, $data['category'], $data['period'], $data['start_date']
));
if ($existing) {
// 更新现有预算
return $this->db->update(
$this->table_name,
array('budget_amount' => floatval($data['budget_amount'])),
array('id' => $existing),
array('%f'),
array('%d')
);
} else {
// 插入新预算
return $this->db->insert(
$this->table_name,
array(
'user_id' => $user_id,
'category' => sanitize_text_field($data['category']),
'budget_amount' => floatval($data['budget_amount']),
'period' => sanitize_text_field($data['period']),
'start_date' => sanitize_text_field($data['start_date']),
'end_date' => $data['end_date'] ? sanitize_text_field($data['end_date']) : null
),
array('%d', '%s', '%f', '%s', '%s', '%s')
);
}
}
// 获取用户预算执行情况
public function get_budget_progress($user_id, $period = 'current_month') {
global $wpdb;
// 确定日期范围
if ($period === 'current_month') {
$start_date = date('Y-m-01');
$end_date = date('Y-m-t');
} elseif ($period === 'current_year') {
$start_date = date('Y-01-01');
$end_date = date('Y-12-31');
} else {
// 自定义日期范围
$date_range = explode('_to_', $period);
$start_date = $date_range[0];
$end_date = $date_range[1];
}
// 获取预算数据
$budgets = $wpdb->get_results($wpdb->prepare(
"SELECT category, budget_amount, period
FROM {$this->table_name}
WHERE user_id = %d
AND start_date <= %s
AND (end_date >= %s OR end_date IS NULL)",
$user_id, $end_date, $start_date
));
$progress_data = array();
foreach ($budgets as $budget) {
// 获取该类别在指定期间的支出总额
$transaction_table = $wpdb->prefix . 'pfm_transactions';
$actual_spent = $wpdb->get_var($wpdb->prepare(
"SELECT SUM(amount)
FROM {$transaction_table}
WHERE user_id = %d
AND category = %s
AND type = 'expense'
AND transaction_date BETWEEN %s AND %s",
$user_id, $budget->category, $start_date, $end_date
)) ?: 0;
$progress_data[] = array(
'category' => $budget->category,
'budget_amount' => floatval($budget->budget_amount),
'actual_spent' => floatval($actual_spent),
'remaining' => floatval($budget->budget_amount) - floatval($actual_spent),
'usage_percentage' => $budget->budget_amount > 0 ?
(floatval($actual_spent) / floatval($budget->budget_amount)) * 100 : 0
);
}
return $progress_data;
}
}
4.2 预算管理界面
创建预算管理页面模板:
<!-- 在templates/budgets.php中 -->
<div class="wrap pfm-budgets">
<h1>预算管理</h1>
<div class="pfm-tabs">
<button class="pfm-tab-button active" data-tab="current-budgets">当前预算</button>
<button class="pfm-tab-button" data-tab="set-budget">设置预算</button>
<button class="pfm-tab-button" data-tab="budget-history">历史预算</button>
</div>
<div id="current-budgets" class="pfm-tab-content active">
<h2>当前预算执行情况</h2>
<div class="pfm-period-selector">
<label for="budget-period">查看期间:</label>
<select id="budget-period">
<option value="current_month">本月</option>
<option value="current_year">本年</option>
<option value="last_month">上月</option>
<option value="last_year">去年</option>
</select>
</div>
<div class="pfm-budget-progress-container">
<?php foreach ($budget_progress as $item): ?>
<div class="pfm-budget-item">
<div class="pfm-budget-header">
<h3><?php echo esc_html($item['category']); ?></h3>
<span class="pfm-budget-amount">预算:¥<?php echo number_format($item['budget_amount'], 2); ?></span>
</div>
<div class="pfm-progress-bar-container">
<div class="pfm-progress-bar">
<div class="pfm-progress-fill"
style="width: <?php echo min($item['usage_percentage'], 100); ?>%;
background-color: <?php echo $item['usage_percentage'] > 90 ? '#f44336' : ($item['usage_percentage'] > 70 ? '#ff9800' : '#4CAF50'); ?>">
</div>
</div>
<div class="pfm-progress-text">
<span>已用:¥<?php echo number_format($item['actual_spent'], 2); ?></span>
<span>剩余:¥<?php echo number_format($item['remaining'], 2); ?></span>
<span>使用率:<?php echo number_format($item['usage_percentage'], 1); ?>%</span>
</div>
</div>
<?php if ($item['usage_percentage'] > 100): ?>
<div class="pfm-budget-alert">
<span class="dashicons dashicons-warning"></span>
已超出预算 <?php echo number_format($item['usage_percentage'] - 100, 1); ?>%
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
<div id="set-budget" class="pfm-tab-content">
<h2>设置新预算</h2>
<form id="pfm-budget-form" method="post">
<?php wp_nonce_field('pfm_set_budget', 'pfm_budget_nonce'); ?>
<div class="pfm-form-row">
<label for="budget-category">预算类别</label>
<select id="budget-category" name="category" required>
<option value="">选择类别</option>
<option value="餐饮">餐饮</option>
<option value="交通">交通</option>
<option value="购物">购物</option>
<option value="娱乐">娱乐</option>
<option value="住房">住房</option>
<option value="医疗">医疗</option>
<option value="教育">教育</option>
<option value="其他">其他</option>
</select>
</div>
<div class="pfm-form-row">
<label for="budget-amount">预算金额 (¥)</label>
<input type="number" id="budget-amount" name="budget_amount" step="0.01" min="0" required>
</div>
<div class="pfm-form-row">
<label for="budget-period">预算周期</label>
<select id="budget-period" name="period" required>
<option value="monthly">月度预算</option>
<option value="yearly">年度预算</option>
<option value="custom">自定义周期</option>
</select>
</div>
<div id="custom-period-fields" style="display: none;">
<div class="pfm-form-row">
<label for="budget-start-date">开始日期</label>
<input type="date" id="budget-start-date" name="start_date">
</div>
<div class="pfm-form-row">
<label for="budget-end-date">结束日期</label>
<input type="date" id="budget-end-date" name="end_date">
</div>
</div>
<div class="pfm-form-actions">
<button type="submit" class="button button-primary">保存预算</button>
<button type="reset" class="button">重置</button>
</div>
</form>
</div>
</div>
第五部分:数据可视化与报表功能
5.1 图表数据接口
创建API接口提供图表数据:
// 在includes/class-pfm-api.php中
class PFM_API {
public function __construct() {
add_action('wp_ajax_pfm_get_chart_data', array($this, 'get_chart_data'));
add_action('wp_ajax_nopriv_pfm_get_chart_data', array($this, 'require_login'));
}
public function get_chart_data() {
// 验证用户权限
if (!is_user_logged_in()) {
wp_die('请先登录');
}
$user_id = get_current_user_id();
$chart_type = sanitize_text_field($_POST['chart_type']);
$period = sanitize_text_field($_POST['period']);
switch ($chart_type) {
case 'monthly_trend':
$data = $this->get_monthly_trend_data($user_id, $period);
break;
case 'category_distribution':
$data = $this->get_category_distribution_data($user_id, $period);
break;
case 'budget_vs_actual':
$data = $this->get_budget_vs_actual_data($user_id, $period);
break;
default:
$data = array('error' => '无效的图表类型');
}
wp_send_json_success($data);
}
private function get_monthly_trend_data($user_id, $months = 6) {
global $wpdb;
$end_date = date('Y-m-d');
$start_date = date('Y-m-d', strtotime("-$months months"));
$transaction_table = $wpdb->prefix . 'pfm_transactions';
// 获取月度收入支出数据
$results = $wpdb->get_results($wpdb->prepare(
"SELECT
DATE_FORMAT(transaction_date, '%%Y-%%m') as month,
SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) as income,
SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) as expense
FROM {$transaction_table}
WHERE user_id = %d
AND transaction_date BETWEEN %s AND %s
GROUP BY DATE_FORMAT(transaction_date, '%%Y-%%m')
ORDER BY month",
$user_id, $start_date, $end_date
));
$labels = array();
$income_data = array();
$expense_data = array();
foreach ($results as $row) {
$labels[] = $row->month;
$income_data[] = floatval($row->income);
$expense_data[] = floatval($row->expense);
}
return array(
'labels' => $labels,
'datasets' => array(
array(
'label' => '收入',
'data' => $income_data,
'borderColor' => '#4CAF50',
'backgroundColor' => 'rgba(76, 175, 80, 0.1)',
'fill' => true
),
array(
'label' => '支出',
'data' => $expense_data,
'borderColor' => '#f44336',
'backgroundColor' => 'rgba(244, 67, 54, 0.1)',
'fill' => true
)
)
);
}
private function get_category_distribution_data($user_id, $period = 'current_month') {
global $wpdb;
// 确定日期范围
if ($period === 'current_month') {
$start_date = date('Y-m-01');
$end_date = date('Y-m-d');
} else {
$start_date = date('Y-01-01');
$end_date = date('Y-12-31');
}
$transaction_table = $wpdb->prefix . 'pfm_transactions';
$results = $wpdb->get_results($wpdb->prepare(
"SELECT category, SUM(amount) as total
FROM {$transaction_table}
WHERE user_id = %d
AND type = 'expense'
AND transaction_date BETWEEN %s AND %s
GROUP BY category
ORDER BY total DESC",
$user_id, $start_date, $end_date
));
$labels = array();
$data = array();
$background_colors = array();
$border_colors = array();
// 预定义颜色方案
$color_palette = array(
'#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0',
'#9966FF', '#FF9F40', '#8AC926', '#1982C4',
'#6A4C93', '#F15BB5', '#00BBF9', '#00F5D4'
);
foreach ($results as $index => $row) {
$labels[] = $row->category;
$data[] = floatval($row->total);
$color_index = $index % count($color_palette);
$background_colors[] = $color_palette[$color_index] . '80'; // 添加透明度
$border_colors[] = $color_palette[$color_index];
}
return array(
'labels' => $labels,
'datasets' => array(
array(
'data' => $data,
'backgroundColor' => $background_colors,
'borderColor' => $border_colors,
'borderWidth' => 1
)
)
);
}
}
5.2 图表渲染与交互
创建JavaScript代码来渲染图表:
// 在assets/js/pfm-charts.js中
jQuery(document).ready(function($) {
// 图表实例存储
var pfmCharts = {};
// 初始化月度趋势图表
function initMonthlyTrendChart() {
var ctx = document.getElementById('pfm-monthly-trend-chart').getContext('2d');
// 获取数据
$.ajax({
url: pfm_ajax.ajax_url,
type: 'POST',
data: {
action: 'pfm_get_chart_data',
chart_type: 'monthly_trend',
period: '6_months',
nonce: pfm_ajax.nonce
},
success: function(response) {
if (response.success) {
pfmCharts.monthlyTrend = new Chart(ctx, {
type: 'line',
data: response.data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
},
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': ¥' + context.parsed.y.toFixed(2);
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return '¥' + value;
}
}
}
}
}
});
}
}
});
}
// 初始化分类分布图表
function initCategoryDistributionChart() {
var ctx = document.getElementById('pfm-category-chart').getContext('2d');
$.ajax({
url: pfm_ajax.ajax_url,
type: 'POST',
data: {
action: 'pfm_get_chart_data',
chart_type: 'category_distribution',
period: 'current_month',
nonce: pfm_ajax.nonce
},
success: function(response) {
if (response.success) {
pfmCharts.categoryDistribution = new Chart(ctx, {
type: 'doughnut',
data: response.data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
},
tooltip: {
callbacks: {
label: function(context) {
var label = context.label || '';
var value = context.parsed || 0;
var total = context.dataset.data.reduce((a, b) => a + b, 0);
var percentage = Math.round((value / total) * 100);
return label + ': ¥' + value.toFixed(2) + ' (' + percentage + '%)';
}
}
}
}
}
});
}
}
});
}
// 更新图表数据
function updateChart(chartType, period) {
if (pfmCharts[chartType]) {
$.ajax({
url: pfm_ajax.ajax_url,
type: 'POST',
data: {
action: 'pfm_get_chart_data',
chart_type: chartType,
period: period,
nonce: pfm_ajax.nonce
},
success: function(response) {
if (response.success) {
pfmCharts[chartType].data = response.data;
pfmCharts[chartType].update();
}
}
});
}
}
// 初始化所有图表
if ($('#pfm-monthly-trend-chart').length) {
initMonthlyTrendChart();
}
if ($('#pfm-category-chart').length) {
initCategoryDistributionChart();
}
// 图表控制事件
$('.pfm-chart-controls select').on('change', function() {
var chartType = $(this).data('chart-type');
var period = $(this).val();
updateChart(chartType, period);
});
});
5.3 报表生成功能
创建报表生成功能:
// 在includes/class-pfm-reports.php中
class PFM_Reports {
public function generate_monthly_report($user_id, $year, $month) {
global $wpdb;
$start_date = sprintf('%04d-%02d-01', $year, $month);
$end_date = date('Y-m-t', strtotime($start_date));
$transaction_table = $wpdb->prefix . 'pfm_transactions';
$budget_table = $wpdb->prefix . 'pfm_budgets';
// 获取月度汇总数据
$summary = $wpdb->get_row($wpdb->prepare(
"SELECT
