捕梦者基础框架API接口
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

219 lines
6.6 KiB

<?php
/**
* Created by 花密欧团队.
* User: 云掌.帮德
* Date: 2020/3/8 22:30
* Desc: 行为日志类
*/
namespace service;
use think\facade\Db;
class ActionLog
{
/**
* 系统日志表
* @var string
*/
private $table = 'system_action_log';
/**
* 系统用户表
* @var string
*/
private $table_manager = 'system_user';
/**
* 禁止写入日志的控制器名称
* @var array
*/
private $_controller = [];
/**
* 修改后数据
* @var array
*/
private $_data = [];
/**
* 修改前数据
* @var array
*/
private $_origin = [];
/**
* 系统管理员信息
* @var string
*/
private $sys_manager = '';
private static $instance = null;
private function __construct()
{
}
/**
* 禁止克隆
*/
private function __clone()
{
// TODO: Implement __clone() method.
}
/**
* 返回单例对象
* @return JwtAuth|null
*/
public static function getInstance()
{
if (!self::$instance instanceof self) {
self::$instance = new self();
}
return self::$instance;
}
/**
* @param array $_data 创建或者修改的最新数据
* @param array $_origin 修改或删除前的源数据
* @param string $_sql 数据sql
* @return bool
*/
public function write(array $_data = [], array $_origin = [], string $_sql = ''): bool
{
if (in_array(\request()->controller(), $this->_controller)) {
return false;
}
$_param = request()->param();
$this->_data = array_merge($_data, $_param);
$this->_origin = $_origin;
$this->sys_manager = $this->getSysManager();
//增加日志记录
$data = [
'site_id' => defined('SITE_ID') ? SITE_ID : $this->_data['site_id'] ?? 0,
'user_id' => defined('UID') ? UID : $this->_data['user_id'] ?? 0,
'username' => $this->sys_manager['username'] ?? '',
'action_ip' => ip2long(request()->ip()),
'request_method' => request()->method(),
'request_param' => json_encode($_param),
'model' => request()->baseUrl(),
'url' => request()->host() . request()->url(),
'spend_time' => round(microtime(true) - request()->time(), 4),
'record_id' => $_data['id'] ?? $_param['id'] ?? 0, //数据表id
'remark' => $this->replaceLog(), //admin在2018年12月23 17:20:48复制了栏目。权限节点cloud/column/copy,记录编号1。
'data' => json_encode($_data),
'origin' => json_encode($_origin),
'sql' => $_sql,
'client_browser' => get_client_browser(),
'client_os' => get_client_os(),
'client_device' => request()->header('client-device') ?? get_client_os(),
'update_time' => time(),
'create_time' => time(),
];
return Db::table($this->table)->insert($data);
}
/**
* 写入日志数据
* @return string|string[]|void
* @throws \ReflectionException
*/
private function replaceLog()
{
//通过注解获取以下信息数据再解析
// @Log [sys_name]在[sys_time]创建了管理员:[username]
// @Log [sys_name]在[sys_time]修改了[origin_username]管理员账号为[username]
//解析数据
$annot = $this->getAnnotations();
if (!$annot) {
return '未检测到日志信息模型,请检查CURR_THIS反射常量!!!';
}
preg_match_all('/\[(\S+?)\]/', $annot, $match);
list($find, $replace) = $match;
foreach ($replace as $k => $v) {
switch ($v) {
case 'sys_name':
$replace[$k] = $this->sys_manager['username'] ?? '';
break;
case 'sys_time':
$replace[$k] = date('Y-m-d H:i:s');
break;
default:
if (strpos($v, 'origin_') === 0) {
//判断是否含有源数据的字段标识 origin_
$replace[$k] = $this->_origin[str_replace('origin_', '', $v)];
} elseif (strpos($v, 'dictionary_') === 0) {
//判断是否含有数据字典的标识 dictionary_
$filter_name = str_replace('dictionary_', '', $v);
//如果字典有值就替换 否则保持原数据
$replace[$k] = $this->getDictionary($filter_name)[$this->_data[$filter_name]] ?? $this->_data[$filter_name];
} else {
//默认返回原数据值
$replace[$k] = $this->_data[$v] ?? '{变量未知}';
}
}
}
$annot = str_replace($find, $replace, $annot);
return $annot;
}
/**
* 通过反射类获取PHP类的注释
* @return string|void
* @throws \ReflectionException
*/
private function getAnnotations()
{
if (!defined('CURR_THIS')) {
return;
}
$class = new \ReflectionClass(CURR_THIS);
$docComment = $class->getMethod(request()->action())->getDocComment();
return get_doc_comment($docComment, 'Log');
// return '[sys_name]在[sys_time]创建了管理员账号:[username]';
// return '[sys_name]在[sys_time]修改了[origin_username]管理员账号为:[username]'; //指定字段后的修改变化
// return '[sys_name]在[sys_time]删除了管理员账号:[username]';
// return '[sys_name]在[sys_time]:更改了管理员状态为:[dictionary_status]';
}
/**
* 获取系统管理员用户信息
* @param string $field
* @return array|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getSysManager($field = '')
{
$_db = Db::table($this->table_manager);
if ($field) {
return $_db->value($field);
}
$user_id = defined('UID') ? UID : $this->_data['user_id'] ?? 0;
if (empty($user_id)) {
return;
}
return $_db->find($user_id);
}
/**
* 获取数据库字典数据
* @param string $field
*/
private function getDictionary($field = '')
{
if ($field) {
return config('dictionary.sqlfields.' . $field);
}
return config('dictionary.sqlfields');
}
}