// +---------------------------------------------------------------------- declare(strict_types=1); namespace app\backend\controller; use think\facade\Db; use ywxapp\controller\BackendBase; use ywxapp\library\AdminLogger; /** * 管理员操作日志 * * 日志来源: * - 后台所有写操作:BackendBase 的 create / edit / del / destroy / restore / multi 成功后自动留痕; * - 登录与退出:BackendBase::login() / logout(); * - 业务代码可直接 AdminLogger::write('动作', '摘要') 补充关键操作。 * * 权限节点(首次访问自动补录):adminlog:index / adminlog:delete / adminlog:clean * * @author ywxapp */ class Adminlog extends BackendBase { use EnsuresPower; protected $noNeedLogin = []; protected $noNeedVerify = []; /** * 进程内只补录一次权限 * @var bool */ protected static $powerChecked = false; protected function initialize() { if (!self::$powerChecked) { self::$powerChecked = true; $this->ensureMenus(); } } /** * 列表 */ public function index() { if ($this->request->isAjax()) { $page = $this->request->param('page/d', 1); $limit = $this->request->param('limit/d', 20); $kw = trim((string) $this->request->param('keyword', '')); $action = trim((string) $this->request->param('action', '')); $start = trim((string) $this->request->param('start', '')); $end = trim((string) $this->request->param('end', '')); $query = Db::name('backend_log')->alias('l') ->leftJoin('backend_admin a', 'a.id = l.aid') ->field('l.*, a.account, a.nickname'); if ($kw !== '') { // 注意:本 ORM 版本的 whereLike 对带表别名字段会抛 // 「where express error」,统一用 where(field, 'like', ...) $query->where(function ($q) use ($kw) { $q->where('l.remark', 'like', '%' . $kw . '%') ->whereOr('l.ip', 'like', '%' . $kw . '%') ->whereOr('a.account', 'like', '%' . $kw . '%') ->whereOr('a.nickname', 'like', '%' . $kw . '%'); }); } if ($action !== '') { $query->where('l.action', 'like', '%' . $action . '%'); } if ($start !== '') { $query->where('l.create_at', '>=', strtotime($start . ' 00:00:00')); } if ($end !== '') { $query->where('l.create_at', '<=', strtotime($end . ' 23:59:59')); } $total = (int) $query->count(); $list = $query->order('l.id', 'desc') ->page($page, $limit) ->select() ->toArray(); foreach ($list as &$row) { $row['create_at_text'] = $row['create_at'] ? date('Y-m-d H:i:s', (int) $row['create_at']) : '-'; $row['operator'] = $row['account'] ?: ($row['aid'] ? ('#' . $row['aid']) : '系统'); } $this->result->setCount($total)->success($list); } // 动作类型下拉:取表里出现过的动作,便于筛选 $actions = Db::name('backend_log') ->field('action, COUNT(*) AS total') ->group('action') ->order('total', 'desc') ->limit(50) ->select() ->toArray(); $this->assign('actions', $actions); return $this->fetch(); } /** * 删除(支持逗号分隔批量) */ public function delete() { if (! $this->request->isPost()) { $this->result->error('请求方式错误', 405); } $ids = $this->request->param('ids', ''); $ids = is_array($ids) ? $ids : array_filter(explode(',', (string) $ids)); if (empty($ids)) { $this->result->error('请选择要删除的日志'); } $count = Db::name('backend_log')->whereIn('id', $ids)->delete(); AdminLogger::write('adminlog/delete', '删除日志 ' . $count . ' 条'); $this->result->success(['count' => $count], '已删除 ' . $count . ' 条'); } /** * 清理:按保留天数删除,days=0 表示清空 */ public function clean() { if (! $this->request->isPost()) { $this->result->error('请求方式错误', 405); } $days = $this->request->param('days/d', 30); if ($days < 0 || $days > 3650) { $this->result->error('保留天数应在 0 ~ 3650 之间(0=清空)'); } $count = AdminLogger::clean($days); AdminLogger::write('adminlog/clean', ($days > 0 ? ('清理 ' . $days . ' 天前日志') : '清空日志') . ',共 ' . $count . ' 条'); $this->result->success(['count' => $count], $days > 0 ? ('已清理 ' . $count . ' 条(保留最近 ' . $days . ' 天)') : ('已清空 ' . $count . ' 条')); } }