本文目录导读:

在PHP项目中实现自定义报表查询模板的保存,核心思路是将用户的查询条件(筛选字段、排序规则、过滤条件等)序列化存储,并支持按模板名称加载,以下是完整的实现方案:
数据库设计
-- 报表模板表
CREATE TABLE report_templates (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL, -- 所属用户
report_type VARCHAR(50), -- 报表类型(如:order_report, user_report)
template_name VARCHAR(100), -- 模板名称
template_data TEXT, -- 序列化的查询条件JSON
is_default TINYINT DEFAULT 0, -- 是否默认模板
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_user_report (user_id, report_type)
);
template_data 字段示例(JSON格式):
{
"filters": [
{"field": "order_date", "operator": "between", "value": ["2024-01-01", "2024-01-31"]},
{"field": "status", "operator": "in", "value": ["paid", "shipped"]},
{"field": "amount", "operator": ">=", "value": 100}
],
"sort": {"field": "order_date", "order": "DESC"},
"columns": ["order_id", "customer_name", "amount", "status"],
"group_by": ["status"],
"record_limit": 100
}
后端PHP实现
1 保存模板
<?php
// save_template.php
require_once 'db.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$userId = $_SESSION['user_id'];
$reportType = $_POST['report_type'] ?? '';
$templateName = $_POST['template_name'] ?? '';
$templateData = $_POST['template_data'] ?? []; // 前端传来的JSON对象
// 参数验证
if (empty($reportType) || empty($templateName) || empty($templateData)) {
http_response_code(400);
echo json_encode(['error' => '缺少必要参数']);
exit;
}
// 序列化查询条件
$serializedData = json_encode($templateData, JSON_UNESCAPED_UNICODE);
// 检查是否设置为默认模板
$isDefault = isset($_POST['set_default']) && $_POST['set_default'] ? 1 : 0;
// 如果设置为默认,先取消该用户该类型的所有默认
if ($isDefault) {
$stmt = $pdo->prepare("UPDATE report_templates SET is_default = 0 WHERE user_id = ? AND report_type = ?");
$stmt->execute([$userId, $reportType]);
}
// 插入或更新(如果同名则更新)
$stmt = $pdo->prepare("
INSERT INTO report_templates (user_id, report_type, template_name, template_data, is_default)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
template_data = VALUES(template_data),
is_default = VALUES(is_default),
updated_at = NOW()
");
try {
$stmt->execute([$userId, $reportType, $templateName, $serializedData, $isDefault]);
echo json_encode(['success' => true, 'message' => '模板保存成功']);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => '保存失败: ' . $e->getMessage()]);
}
}
2 加载模板列表
<?php
// get_templates.php
require_once 'db.php';
$userId = $_SESSION['user_id'];
$reportType = $_GET['report_type'] ?? '';
$stmt = $pdo->prepare("SELECT id, template_name, is_default, created_at FROM report_templates
WHERE user_id = ? AND report_type = ?
ORDER BY is_default DESC, created_at DESC");
$stmt->execute([$userId, $reportType]);
$templates = $stmt->fetchAll(PDO::FETCH_ASSOC);
header('Content-Type: application/json');
echo json_encode($templates);
3 加载单个模板
<?php
// load_template.php
require_once 'db.php';
$templateId = $_GET['id'] ?? 0;
$stmt = $pdo->prepare("SELECT template_data FROM report_templates WHERE id = ? AND user_id = ?");
$stmt->execute([$templateId, $_SESSION['user_id']]);
$template = $stmt->fetch(PDO::FETCH_ASSOC);
if ($template) {
$templateData = json_decode($template['template_data'], true);
header('Content-Type: application/json');
echo json_encode($templateData);
} else {
http_response_code(404);
echo json_encode(['error' => '模板不存在']);
}
前端JavaScript实现
1 保存模板
// 假设已有查询条件对象 reportFilters
const reportFilters = {
filters: [
{ field: 'order_date', operator: 'between', value: ['2024-01-01', '2024-01-31'] },
{ field: 'status', operator: 'in', value: ['paid', 'shipped'] }
],
sort: { field: 'order_date', order: 'DESC' },
columns: ['order_id', 'customer_name', 'amount', 'status']
};
function saveTemplate() {
const templateName = prompt('请输入模板名称:');
if (!templateName) return;
const setDefault = confirm('是否设为默认模板?');
fetch('/save_template.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
report_type: 'order_report',
template_name: templateName,
template_data: reportFilters,
set_default: setDefault
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('模板保存成功');
loadTemplateList(); // 刷新模板列表
}
})
.catch(error => console.error('保存失败:', error));
}
2 加载模板列表示例
function loadTemplateList() {
fetch('/get_templates.php?report_type=order_report')
.then(response => response.json())
.then(templates => {
const select = document.getElementById('templateSelect');
select.innerHTML = '<option value="">请选择模板</option>';
templates.forEach(template => {
const option = document.createElement('option');
option.value = template.id;
option.textContent = template.template_name + (template.is_default ? ' (默认)' : '');
select.appendChild(option);
});
});
}
function applyTemplate(templateId) {
fetch(`/load_template.php?id=${templateId}`)
.then(response => response.json())
.then(templateData => {
// 将查询条件应用到报表界面
reportFilters = templateData;
applyFiltersToUI(templateData);
reloadReport();
});
}
前端UI交互参考
<div class="report-toolbar">
<button onclick="saveTemplate()">保存为模板</button>
<select id="templateSelect" onchange="if(this.value) applyTemplate(this.value)">
<option value="">选择模板</option>
</select>
<button onclick="loadTemplateList()">刷新模板列表</button>
</div>
高级功能扩展
1 模板分类与权限
-- 添加模板分类和权限控制 ALTER TABLE report_templates ADD COLUMN category VARCHAR(50) DEFAULT 'personal'; ALTER TABLE report_templates ADD COLUMN is_public TINYINT DEFAULT 0;
2 模板版本管理
-- 模板版本表
CREATE TABLE template_versions (
id INT AUTO_INCREMENT PRIMARY KEY,
template_id INT NOT NULL,
template_data TEXT,
version INT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
change_log TEXT
);
3 模板分享功能
// 分享模板时生成分享码
function shareTemplate($templateId) {
$shareCode = bin2hex(random_bytes(8));
// 存储分享关系
$stmt = $pdo->prepare("INSERT INTO template_shares (template_id, share_code) VALUES (?, ?)");
$stmt->execute([$templateId, $shareCode]);
return $shareCode;
}
安全注意事项
- 序列化安全:始终使用
json_encode/json_decode,不要使用serialize() - 权限校验:加载模板时必须校验用户所有权
- SQL注入防护:使用参数化查询
- XSS防护:前端显示模板名称时进行HTML转义
- 数据验证:保存时验证查询结构的合法性,防止恶意数据
完整工作流程
用户设置查询条件 → 点击“保存模板”
→ 填写模板名称 → 选择是否默认
→ 前端序列化查询条件为JSON → POST请求发送到后端
→ 后端验证并保存到数据库
→ 返回成功提示 → 前端刷新模板列表
用户选择模板 → 选择下拉框 → 触发change事件
→ 请求后端加载对应ID的模板
→ 获取JSON数据 → 恢复到报表查询界面
→ 自动执行查询
这套方案适用于大多数PHP报表系统的模板管理需求,可根据实际业务复杂度进行适当调整。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播