Files
think-plugs-recorder/DESIGN.md
2025-08-13 10:39:09 +08:00

15 KiB

think-plugs-recorder 插件设计文档

1. 功能需求分析

1.1 项目概述

think-plugs-recorder 是一个基于 ThinkAdmin v6.1 的操作记录插件,用于记录用户在系统中的各种操作行为,提供完整的操作日志追踪功能。

1.2 核心功能需求

1.2.1 操作记录功能

  • 记录用户的读取操作
  • 记录用户的自定义操作
  • 支持记录操作数据的类型和ID
  • 支持记录关联数据的类型和ID

1.2.2 记录字段要求

  1. 操作类型 (operation_type): 如 create, read, update, delete, custom 等
  2. 操作说明 (operation_desc): 具体的操作描述
  3. 用户ID (user_id): 操作用户的唯一标识
  4. 用户昵称 (user_nickname): 操作用户的显示名称
  5. 操作时间 (operation_time): 操作发生的时间戳
  6. 当前操作数据类型 (data_type): 如 user, order, product 等
  7. 当前操作数据ID (data_id): 具体数据记录的ID
  8. 关联数据类型 (related_type): 关联数据的类型(可选)
  9. 关联数据ID (related_id): 关联数据的ID(可选)

1.2.3 功能扩展需求

  • 支持批量记录操作
  • 支持按多种条件查询操作记录
  • 支持操作记录的导出功能
  • 支持自定义操作类型配置
  • 支持敏感操作的特殊标记

1.3 非功能性需求

  • 性能要求: 记录操作不应影响主业务性能
  • 存储要求: 支持大量历史记录存储
  • 安全要求: 操作记录不可被随意修改或删除
  • 可维护性: 提供清晰的接口和配置选项

2. 数据库设计

2.1 主要数据表设计

2.1.1 操作记录表 (jl_recorder_log)

CREATE TABLE `jl_recorder_log` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '记录ID',
  `operation_type` varchar(50) NOT NULL DEFAULT '' COMMENT '操作类型',
  `operation_desc` varchar(500) NOT NULL DEFAULT '' COMMENT '操作说明',
  `user_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '操作用户ID',
  `user_nickname` varchar(100) NOT NULL DEFAULT '' COMMENT '操作用户昵称',
  `data_type` varchar(100) NOT NULL DEFAULT '' COMMENT '操作数据类型',
  `data_id` varchar(100) NOT NULL DEFAULT '' COMMENT '操作数据ID',
  `related_type` varchar(100) NOT NULL DEFAULT '' COMMENT '关联数据类型',
  `related_id` varchar(100) NOT NULL DEFAULT '' COMMENT '关联数据ID',
  `request_method` varchar(10) NOT NULL DEFAULT '' COMMENT '请求方法',
  `request_url` varchar(500) NOT NULL DEFAULT '' COMMENT '请求URL',
  `request_ip` varchar(50) NOT NULL DEFAULT '' COMMENT '请求IP',
  `user_agent` varchar(500) NOT NULL DEFAULT '' COMMENT '用户代理',
  `extra_data` text COMMENT '额外数据(JSON格式)',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_operation_type` (`operation_type`),
  KEY `idx_data_type_id` (`data_type`, `data_id`),
  KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='操作记录表';

2.1.2 预置操作类型说明

操作类型直接使用中文字符串,常用的操作类型包括:

  • 创建: 新增数据记录
  • 读取: 查看数据详情
  • 更新: 修改数据记录
  • 删除: 删除数据记录
  • 导出: 导出数据
  • 登录: 用户登录
  • 登出: 用户登出
  • 审核: 审核操作
  • 发布: 发布操作

2.2 索引设计说明

  • idx_user_id: 按用户查询操作记录
  • idx_operation_type: 按操作类型查询
  • idx_data_type_id: 按数据类型和ID查询特定数据的操作记录
  • idx_created_at: 按时间范围查询操作记录

3. 架构设计

3.1 插件架构

think-plugs-recorder/
├── composer.json                 # Composer配置
├── DESIGN.md                    # 设计文档
├── README.md                    # 使用说明
├── src/                         # 源码目录
│   ├── Service.php             # 插件服务类
│   ├── model/                  # 模型目录
│   │   └── RecorderLog.php     # 操作记录模型
│   ├── service/                # 服务目录
│   │   └── RecorderService.php # 核心服务类
│   ├── controller/             # 控制器目录 (可选)
│   │   └── RecorderController.php # 记录管理控制器
│   ├── middleware/             # 中间件目录
│   │   └── RecorderMiddleware.php # 操作记录中间件
│   └── helper/                 # 辅助工具目录
│       └── ViewHelper.php      # 视图辅助类
├── stc/                        # 静态资源
│   └── database/               # 数据库迁移脚本
│       └── 20241201000001_create_recorder_logs_table.php
└── view/                       # 视图文件
    └── recorder/
        ├── components/             # 视图组件
        │   ├── record_list.html   # 记录列表组件
        │   ├── record_item.html   # 记录项组件
        │   └── record_timeline.html # 时间线组件
        ├── index.html             # 管理页面
        └── detail.html            # 详情页面

3.2 核心类设计

3.2.1 RecorderService 核心服务类

<?php
namespace jerryyan\recorder\service;

class RecorderService
{
    // 记录操作
    public function record(array $data): bool;
    
    // 批量记录操作
    public function batchRecord(array $records): bool;
    
    // 查询操作记录
    public function query(array $conditions = []): array;
    
    // 获取用户操作记录
    public function getUserRecords(int $userId, array $conditions = []): array;
    
    // 获取数据操作记录
    public function getDataRecords(string $dataType, string $dataId): array;
    
    // 导出操作记录
    public function export(array $conditions = []): string;
    
    // 清理过期记录
    public function cleanup(int $days = 90): int;
}

3.2.2 RecorderLog 数据模型

<?php
namespace jerryyan\recorder\model;

class RecorderLog extends \think\admin\Model
{
    
    // 自动时间戳
    protected $autoWriteTimestamp = true;
    
    // 字段类型转换
    protected $type = [
        'id' => 'integer',
        'user_id' => 'integer',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];
    
    // 字段验证规则
    protected function getRules(): array;
    
    
    // 获取额外数据
    public function getExtraDataAttr($value): array;
    
    // 设置额外数据
    public function setExtraDataAttr($value): string;
}

3.2.3 ViewHelper 视图辅助类

<?php
namespace jerryyan\recorder\helper;

class ViewHelper
{
    // 获取操作记录数据
    public static function getRecords(array $conditions = []): array;
    
    // 渲染记录列表HTML
    public static function renderList(array $conditions = [], array $options = []): string;
    
    // 渲染记录时间线HTML
    public static function renderTimeline(array $conditions = [], array $options = []): string;
    
    // 渲染单条记录HTML
    public static function renderItem(array $record, array $options = []): string;
    
    // 注册模板函数
    public static function registerTemplateFunctions(): void;
}

3.3 接口设计

3.3.1 记录接口

// 基础记录接口
RecorderService::record([
    'operation_type' => '读取',
    'operation_desc' => '查看用户信息',
    'data_type' => 'user',
    'data_id' => '123',
    'related_type' => 'department',
    'related_id' => '456'
]);

// 自动记录当前用户信息
RecorderService::autoRecord([
    'operation_type' => '创建',
    'operation_desc' => '创建新订单',
    'data_type' => 'order',
    'data_id' => '789'
]);

3.3.2 查询接口

// 查询用户操作记录
$records = RecorderService::getUserRecords(123, [
    'operation_type' => '读取',
    'start_time' => '2024-01-01',
    'end_time' => '2024-12-31'
]);

// 查询数据操作记录
$records = RecorderService::getDataRecords('user', '123');

// 复杂条件查询
$records = RecorderService::query([
    'user_id' => 123,
    'operation_type' => ['读取', '更新'],
    'data_type' => 'user',
    'date_range' => ['2024-01-01', '2024-12-31']
]);

3.3.3 视图调用接口

// 在模板中获取操作记录
{:recorder_get_records(['data_type' => 'user', 'data_id' => $user_id])}

// 渲染记录列表
{:recorder_render_list(['user_id' => $user_id], ['limit' => 10])}

// 渲染时间线
{:recorder_render_timeline(['data_type' => 'order', 'data_id' => $order_id])}

// 渲染单条记录
{:recorder_render_item($record)}

4. 使用方式设计

4.1 手动记录

在业务代码中手动调用记录方法:

use jerryyan\recorder\service\RecorderService;

// 在控制器或服务中记录操作
RecorderService::record([
    'operation_type' => '读取',
    'operation_desc' => '查看用户详情',
    'data_type' => 'user',
    'data_id' => $userId
]);

4.2 中间件自动记录

通过中间件自动记录请求操作:

// 在应用配置中启用中间件
'middleware' => [
    'jerryyan\recorder\middleware\RecorderMiddleware'
]

4.3 模型事件记录

在模型事件中自动记录CRUD操作:

// 在模型中添加事件监听
protected static function onAfterInsert($model) {
    RecorderService::autoRecord([
        'operation_type' => '创建',
        'operation_desc' => '创建' . $model->getTable() . '记录',
        'data_type' => $model->getTable(),
        'data_id' => $model->getPk()
    ]);
}

4.4 视图模板调用

在ThinkPHP模板中直接调用操作记录功能:

4.4.1 获取记录数据

<!-- 获取用户操作记录 -->
{assign name="user_records" value=":recorder_get_records(['user_id' => $user_id, 'limit' => 5])" /}

<!-- 获取特定数据的操作记录 -->
{assign name="data_records" value=":recorder_get_records(['data_type' => 'order', 'data_id' => $order_id])" /}

<!-- 遍历显示记录 -->
{volist name="user_records" id="record"}
<div class="record-item">
    <span class="operation">{$record.operation_type}</span>
    <span class="desc">{$record.operation_desc}</span>
    <span class="time">{$record.created_at}</span>
</div>
{/volist}

4.4.2 渲染HTML组件

<!-- 渲染操作记录列表 -->
<div class="record-section">
    <h4>操作记录</h4>
    {:recorder_render_list(['user_id' => $user_id], ['limit' => 10, 'show_user' => false])}
</div>

<!-- 渲染时间线样式 -->
<div class="timeline-section">
    <h4>操作时间线</h4>
    {:recorder_render_timeline(['data_type' => 'order', 'data_id' => $order_id], ['theme' => 'vertical'])}
</div>

<!-- 在用户详情页显示最近操作 -->
<div class="recent-actions">
    <h5>最近操作</h5>
    {:recorder_render_list(['user_id' => $user_id], ['limit' => 3, 'compact' => true])}
</div>

4.4.3 AJAX异步加载

<!-- 异步加载更多记录 -->
<div id="record-container">
    <div class="record-list">
        {:recorder_render_list(['data_type' => 'user', 'data_id' => $user_id], ['limit' => 10])}
    </div>
    <button onclick="loadMoreRecords()" class="load-more">加载更多</button>
</div>

<script>
function loadMoreRecords() {
    $.post('/recorder/load_more', {
        data_type: 'user',
        data_id: {$user_id},
        offset: $('.record-item').length
    }, function(html) {
        $('.record-list').append(html);
    });
}
</script>

4.4.4 可配置的显示选项

<!-- 带配置选项的记录列表 -->
{assign name="list_options" value="[
    'limit' => 20,
    'show_user' => true,
    'show_ip' => false,
    'date_format' => 'Y-m-d H:i:s',
    'theme' => 'card',
    'show_extra' => false
]" /}

{:recorder_render_list(['user_id' => $user_id], $list_options)}

<!-- 简洁模式的时间线 -->
{:recorder_render_timeline(['data_type' => 'project', 'data_id' => $project_id], ['compact' => true, 'limit' => 5])}

5. 配置设计

5.1 插件配置

return [
    'recorder' => [
        // 是否启用操作记录
        'enabled' => true,
        
        // 自动记录模式
        'auto_record' => [
            'enabled' => true,
            'exclude_operations' => ['读取'], // 排除的操作类型
            'exclude_controllers' => [], // 排除的控制器
        ],
        
        // 记录保留天数
        'retention_days' => 90,
        
        // 敏感操作标记
        'sensitive_operations' => ['删除', '导出'],
        
        // 视图组件配置
        'view' => [
            'default_limit' => 10,
            'date_format' => 'Y-m-d H:i:s',
            'theme' => 'default', // default, card, timeline
            'show_user' => true,
            'show_ip' => false,
            'compact_mode' => false,
        ]
    ]
];

6. 安全考虑

6.1 数据安全

  • 记录表只允许插入和查询,不允许更新和删除
  • 敏感操作需要特殊权限才能查看
  • 支持数据脱敏显示

6.2 性能考虑

  • 异步记录操作日志,不影响主业务
  • 定期清理过期日志
  • 合理的索引设计

6.3 权限控制

  • 基于 ThinkAdmin 的权限系统
  • 不同用户只能查看自己的操作记录
  • 管理员可以查看所有用户的操作记录

7. 扩展计划

7.1 功能扩展

  • 支持操作记录的统计分析
  • 支持异常操作的告警机制
  • 支持操作记录的可视化展示

7.2 集成扩展

  • 支持与其他日志系统集成
  • 支持导出到第三方审计系统
  • 支持API接口调用记录

7.3 视图功能扩展

  • 支持更多主题样式和布局
  • 支持自定义模板和组件
  • 支持实时刷新和WebSocket推送
  • 支持操作记录的图表统计

8. 视图模板函数设计

8.1 注册的模板函数

插件将自动注册以下模板函数供视图调用:

// 获取操作记录数据
function recorder_get_records(array $conditions = []): array

// 渲染记录列表
function recorder_render_list(array $conditions = [], array $options = []): string

// 渲染时间线
function recorder_render_timeline(array $conditions = [], array $options = []): string

// 渲染单条记录
function recorder_render_item(array $record, array $options = []): string

// 获取记录统计
function recorder_get_stats(array $conditions = []): array

8.2 可用的显示选项

$options = [
    'limit' => 10,                    // 显示数量限制
    'show_user' => true,              // 是否显示用户信息
    'show_ip' => false,               // 是否显示IP地址
    'show_extra' => false,            // 是否显示额外数据
    'date_format' => 'Y-m-d H:i:s',   // 日期格式
    'theme' => 'default',             // 主题样式 (default, card, timeline, compact)
    'compact' => false,               // 是否紧凑模式
    'css_class' => '',                // 自定义CSS类
    'template' => '',                 // 自定义模板文件
];

8.3 视图组件样式

插件提供多种预置样式主题:

  • default: 默认列表样式
  • card: 卡片式布局
  • timeline: 时间线布局
  • compact: 紧凑式布局

注意: 此设计文档需要在开始编码前经过确认,确保需求理解准确无误。