From 11fe0b4357afe233dcf0770b1fb67990afdb2629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E6=B3=BD=E7=BD=91?= <”357099073@qq.com“> Date: Mon, 19 May 2025 00:46:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=90=8E=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/Article.php | 17 + app/admin/controller/Index.php | 203 +++++- app/admin/controller/Log.php | 208 +++++++ app/admin/controller/Resources.php | 16 + app/admin/view/index/index.php | 2 +- app/admin/view/index/welcome.php | 576 +++++++++++++++-- app/admin/view/log/login.php | 166 +++++ app/admin/view/log/operation.php | 175 ++++++ app/admin/view/login/index.php | 5 +- config/middleware.php | 9 +- public/static/css/index.css | 6 +- public/static/js/echarts.min.js | 45 ++ public/static/js/jquery.min.js | 2 + .../temp/02890b205219b043551566c44acd91e7.php | 7 +- .../temp/03e4ab61ce303403afa76cd64a82b52f.php | 311 ++++++++++ .../temp/15ce02ee4fbe4bcbe1b70cd1c4c479ed.php | 277 +++++++++ .../temp/34d283a1bcbe58ecbdbcd3d1f0e36700.php | 269 ++++++++ .../temp/413d41632850e6a39f16abf9573c9dfd.php | 177 ++++++ .../temp/6f472d37a02e7e3b8a4ad0660ee03e89.php | 223 +++++++ .../temp/792969fb591a0f355761a1b3bf3d1226.php | 578 ++++++++++++++++-- .../temp/95be89451b9d20c113b1e9b89d74e7ed.php | 260 ++++++++ .../temp/a9d67e4df562a7a96e64c14bb80c557f.php | 218 +++++++ .../temp/c5f36a7772c20379b8b97ddafceff134.php | 4 +- .../temp/e30d87f89492bcc578f378b87aa8db8c.php | 241 ++++++++ .../temp/ed5803675033b1aaf5d5b114c280de83.php | 221 +++++++ .../temp/ee8f615b050a831ad002b94d744ddbec.php | 217 +++++++ .../temp/f0fe9d983bb988825da5431c2353387e.php | 343 +++++++++++ .../temp/402d23cdf323169a38fb26d3649b6ad5.php | 2 +- 28 files changed, 4644 insertions(+), 134 deletions(-) create mode 100644 app/admin/controller/Log.php create mode 100644 app/admin/view/log/login.php create mode 100644 app/admin/view/log/operation.php create mode 100644 public/static/js/echarts.min.js create mode 100644 public/static/js/jquery.min.js create mode 100644 runtime/admin/temp/03e4ab61ce303403afa76cd64a82b52f.php create mode 100644 runtime/admin/temp/15ce02ee4fbe4bcbe1b70cd1c4c479ed.php create mode 100644 runtime/admin/temp/34d283a1bcbe58ecbdbcd3d1f0e36700.php create mode 100644 runtime/admin/temp/413d41632850e6a39f16abf9573c9dfd.php create mode 100644 runtime/admin/temp/6f472d37a02e7e3b8a4ad0660ee03e89.php create mode 100644 runtime/admin/temp/95be89451b9d20c113b1e9b89d74e7ed.php create mode 100644 runtime/admin/temp/a9d67e4df562a7a96e64c14bb80c557f.php create mode 100644 runtime/admin/temp/e30d87f89492bcc578f378b87aa8db8c.php create mode 100644 runtime/admin/temp/ed5803675033b1aaf5d5b114c280de83.php create mode 100644 runtime/admin/temp/ee8f615b050a831ad002b94d744ddbec.php create mode 100644 runtime/admin/temp/f0fe9d983bb988825da5431c2353387e.php diff --git a/app/admin/controller/Article.php b/app/admin/controller/Article.php index 1353321..d0c68e5 100644 --- a/app/admin/controller/Article.php +++ b/app/admin/controller/Article.php @@ -7,6 +7,7 @@ use app\admin\controller\Base; use think\facade\Db; use think\facade\View; use think\facade\Request; +use app\common\service\LogService; class Article extends Base { @@ -411,4 +412,20 @@ class Article extends Base } return json(['code' => 0, 'msg' => '删除成功', 'data' => []]); } + + //统计文章数量 + public function counts() { + $total = Db::table('yz_article') + ->where('delete_time', null) + ->where('status', '<>', 3) + ->count(); + + return json([ + 'code' => 0, + 'msg' => '获取成功', + 'data' => [ + 'total' => $total + ] + ]); + } } \ No newline at end of file diff --git a/app/admin/controller/Index.php b/app/admin/controller/Index.php index 8feb4a9..0cead47 100644 --- a/app/admin/controller/Index.php +++ b/app/admin/controller/Index.php @@ -61,10 +61,206 @@ class Index extends Base{ } # 欢迎页面 public function welcome(){ - View::assign([ - 'time' => date('Y-m-d',$_SERVER['REQUEST_TIME']), + // 获取今日统计数据 + $today = date('Y-m-d'); + $todayStats = Db::name('yz_daily_stats') + ->where('date', $today) + ->find(); + + // 获取最近7天的访问趋势 + $last7Days = Db::name('yz_daily_stats') + ->where('date', '>=', date('Y-m-d', strtotime('-7 days'))) + ->where('date', '<=', $today) + ->order('date', 'asc') + ->select() + ->toArray(); + + // 获取用户增长趋势 + $userGrowth = Db::name('yz_daily_stats') + ->where('date', '>=', date('Y-m-d', strtotime('-30 days'))) + ->where('date', '<=', $today) + ->field('date, new_users, total_users') + ->order('date', 'asc') + ->select() + ->toArray(); + + // 获取资源下载统计 + $resourceStats = Db::name('yz_daily_stats') + ->where('date', '>=', date('Y-m-d', strtotime('-7 days'))) + ->where('date', '<=', $today) + ->field('date, daily_resources, resource_downloads') + ->order('date', 'asc') + ->select() + ->toArray(); + + // 获取文章访问统计 + $articleStats = Db::name('yz_daily_stats') + ->where('date', '>=', date('Y-m-d', strtotime('-7 days'))) + ->where('date', '<=', $today) + ->field('date, daily_articles, article_views') + ->order('date', 'asc') + ->select() + ->toArray(); + + // 获取最近的活动记录 + $recentActivities = $this->getRecentActivities(); + + // 准备图表数据 + $chartData = [ + 'visitTrend' => $this->formatVisitTrendData($last7Days), + 'userGrowth' => $this->formatUserGrowthData($userGrowth), + 'resourceStats' => $this->formatResourceStatsData($resourceStats), + 'articleStats' => $this->formatArticleStatsData($articleStats) + ]; + + // 准备统计数据 + $stats = [ + 'total_users' => $todayStats['total_users'] ?? 0, + 'daily_visits' => $todayStats['daily_visits'] ?? 0, + 'total_articles' => $todayStats['total_articles'] ?? 0, + 'total_resources' => $todayStats['total_resources'] ?? 0, + ]; + + return View::fetch('', [ + 'stats' => $stats, + 'chartData' => $chartData, + 'recentActivities' => $recentActivities ]); - return View::fetch(); + } + + /** + * 获取最近的活动记录 + */ + private function getRecentActivities() + { + $today = date('Y-m-d'); + $activities = []; + + // 获取今日新用户 + $newUsers = Db::name('yz_daily_stats') + ->where('date', $today) + ->value('new_users'); + if ($newUsers > 0) { + $activities[] = [ + 'icon' => '👥', + 'title' => '新增用户 ' . $newUsers . ' 人', + 'time' => '今日' + ]; + } + + // 获取今日文章 + $newArticles = Db::name('yz_daily_stats') + ->where('date', $today) + ->value('daily_articles'); + if ($newArticles > 0) { + $activities[] = [ + 'icon' => '📝', + 'title' => '发布文章 ' . $newArticles . ' 篇', + 'time' => '今日' + ]; + } + + // 获取今日资源 + $newResources = Db::name('yz_daily_stats') + ->where('date', $today) + ->value('daily_resources'); + if ($newResources > 0) { + $activities[] = [ + 'icon' => '📦', + 'title' => '上传资源 ' . $newResources . ' 个', + 'time' => '今日' + ]; + } + + return $activities; + } + + /** + * 格式化访问趋势数据 + */ + private function formatVisitTrendData($data) + { + $dates = []; + $visits = []; + $uvs = []; + + foreach ($data as $item) { + $dates[] = date('m-d', strtotime($item['date'])); + $visits[] = $item['daily_visits']; + $uvs[] = $item['unique_visitors']; + } + + return [ + 'dates' => $dates, + 'visits' => $visits, + 'uvs' => $uvs + ]; + } + + /** + * 格式化用户增长数据 + */ + private function formatUserGrowthData($data) + { + $dates = []; + $newUsers = []; + $totalUsers = []; + + foreach ($data as $item) { + $dates[] = date('m-d', strtotime($item['date'])); + $newUsers[] = $item['new_users']; + $totalUsers[] = $item['total_users']; + } + + return [ + 'dates' => $dates, + 'newUsers' => $newUsers, + 'totalUsers' => $totalUsers + ]; + } + + /** + * 格式化资源统计数据 + */ + private function formatResourceStatsData($data) + { + $dates = []; + $resources = []; + $downloads = []; + + foreach ($data as $item) { + $dates[] = date('m-d', strtotime($item['date'])); + $resources[] = $item['daily_resources']; + $downloads[] = $item['resource_downloads']; + } + + return [ + 'dates' => $dates, + 'resources' => $resources, + 'downloads' => $downloads + ]; + } + + /** + * 格式化文章统计数据 + */ + private function formatArticleStatsData($data) + { + $dates = []; + $articles = []; + $views = []; + + foreach ($data as $item) { + $dates[] = date('m-d', strtotime($item['date'])); + $articles[] = $item['daily_articles']; + $views[] = $item['article_views']; + } + + return [ + 'dates' => $dates, + 'articles' => $articles, + 'views' => $views + ]; } /** @@ -243,4 +439,5 @@ class Index extends Base{ return json(['code'=>1, 'msg'=>$e->getMessage()])->send(); } } + } \ No newline at end of file diff --git a/app/admin/controller/Log.php b/app/admin/controller/Log.php new file mode 100644 index 0000000..c103959 --- /dev/null +++ b/app/admin/controller/Log.php @@ -0,0 +1,208 @@ +where('username', 'like', "%{$username}%"); + } + if ($ip) { + $query = $query->where('ip_address', 'like', "%{$ip}%"); + } + if ($status !== '') { + $query = $query->where('login_status', $status); + } + if ($startTime) { + $query = $query->where('login_time', '>=', $startTime); + } + if ($endTime) { + $query = $query->where('login_time', '<=', $endTime); + } + + $count = $query->count(); + $list = $query->order('id desc') + ->page($page, $limit) + ->select(); + + return json([ + 'code' => 0, + 'msg' => '获取成功', + 'count' => $count, + 'data' => $list + ]); + } + + return View::fetch(); + } + + /** + * 操作日志列表 + */ + public function operation() + { + if (Request::isPost()) { + $page = input('post.page', 1); + $limit = input('post.limit', 10); + $username = input('post.username'); + $module = input('post.module'); + $operation = input('post.operation'); + $status = input('post.status'); + $startTime = input('post.start_time'); + $endTime = input('post.end_time'); + + $query = Db::name('yz_logs_operation'); + + // 搜索条件 + if ($username) { + $query = $query->where('username', 'like', "%{$username}%"); + } + if ($module) { + $query = $query->where('module', 'like', "%{$module}%"); + } + if ($operation) { + $query = $query->where('operation', 'like', "%{$operation}%"); + } + if ($status !== '') { + $query = $query->where('status', $status); + } + if ($startTime) { + $query = $query->where('operation_time', '>=', $startTime); + } + if ($endTime) { + $query = $query->where('operation_time', '<=', $endTime); + } + + $count = $query->count(); + $list = $query->order('id desc') + ->page($page, $limit) + ->select(); + + return json([ + 'code' => 0, + 'msg' => '获取成功', + 'count' => $count, + 'data' => $list + ]); + } + + return View::fetch(); + } + + /** + * 记录操作日志 + */ + protected function recordOperation($operation, $status = 1, $error_message = '') + { + $data = [ + 'username' => session('admin_username'), + 'module' => '日志管理', + 'operation' => $operation, + 'request_method' => Request::method(), + 'request_url' => Request::url(true), + 'request_params' => json_encode(Request::param(), JSON_UNESCAPED_UNICODE), + 'ip_address' => Request::ip(), + 'status' => $status, + 'error_message' => $error_message, + 'operation_time' => date('Y-m-d H:i:s'), + 'execution_time' => 0 + ]; + + Db::name('yz_logs_operation')->insert($data); + } + + /** + * 删除登录日志 + */ + public function deleteLogin() + { + $id = input('post.id'); + try { + if (Db::name('yz_logs_login')->delete($id)) { + $this->recordOperation('删除登录日志'); + return json(['code' => 0, 'msg' => '删除成功']); + } + $this->recordOperation('删除登录日志', 0, '删除失败'); + return json(['code' => 1, 'msg' => '删除失败']); + } catch (\Exception $e) { + $this->recordOperation('删除登录日志', 0, $e->getMessage()); + return json(['code' => 1, 'msg' => '删除失败:' . $e->getMessage()]); + } + } + + /** + * 删除操作日志 + */ + public function deleteOperation() + { + $id = input('post.id'); + try { + if (Db::name('yz_logs_operation')->delete($id)) { + $this->recordOperation('删除操作日志'); + return json(['code' => 0, 'msg' => '删除成功']); + } + $this->recordOperation('删除操作日志', 0, '删除失败'); + return json(['code' => 1, 'msg' => '删除失败']); + } catch (\Exception $e) { + $this->recordOperation('删除操作日志', 0, $e->getMessage()); + return json(['code' => 1, 'msg' => '删除失败:' . $e->getMessage()]); + } + } + + /** + * 清空登录日志 + */ + public function clearLogin() + { + try { + if (Db::name('yz_logs_login')->where('1=1')->delete()) { + $this->recordOperation('清空登录日志'); + return json(['code' => 0, 'msg' => '清空成功']); + } + $this->recordOperation('清空登录日志', 0, '清空失败'); + return json(['code' => 1, 'msg' => '清空失败']); + } catch (\Exception $e) { + $this->recordOperation('清空登录日志', 0, $e->getMessage()); + return json(['code' => 1, 'msg' => '清空失败:' . $e->getMessage()]); + } + } + + /** + * 清空操作日志 + */ + public function clearOperation() + { + try { + if (Db::name('yz_logs_operation')->where('1=1')->delete()) { + $this->recordOperation('清空操作日志'); + return json(['code' => 0, 'msg' => '清空成功']); + } + $this->recordOperation('清空操作日志', 0, '清空失败'); + return json(['code' => 1, 'msg' => '清空失败']); + } catch (\Exception $e) { + $this->recordOperation('清空操作日志', 0, $e->getMessage()); + return json(['code' => 1, 'msg' => '清空失败:' . $e->getMessage()]); + } + } +} \ No newline at end of file diff --git a/app/admin/controller/Resources.php b/app/admin/controller/Resources.php index 8988690..167c8a1 100644 --- a/app/admin/controller/Resources.php +++ b/app/admin/controller/Resources.php @@ -445,4 +445,20 @@ class Resources extends Base return View::fetch(); } + //统计资源数量 + public function counts() { + $total = Db::table('yz_resources') + ->where('delete_time', null) + ->where('status', '<>', 3) + ->count(); + + return json([ + 'code' => 0, + 'msg' => '获取成功', + 'data' => [ + 'total' => $total + ] + ]); + } + } \ No newline at end of file diff --git a/app/admin/view/index/index.php b/app/admin/view/index/index.php index 56a8981..b0bf521 100644 --- a/app/admin/view/index/index.php +++ b/app/admin/view/index/index.php @@ -109,7 +109,7 @@