$this->aUser['group_id']]; $role = AdminUserGroup::where($where)->find(); if($role){ $role['rights'] = (isset($role['rights']) && $role['rights']) ? json_decode($role['rights'],true) : []; } if($role['rights']){ $where = [ ['smid','in',implode(',',$role['rights']) ], ['status','=',1] ]; // 获取所有菜单 $menus = AdminSysMenu::order('type,sort desc')->where($where)->select()->toArray(); // 构建树形结构菜单 $menuTree = []; $menuMap = []; // 先将所有菜单项映射到一个关联数组中 foreach($menus as $item){ $item['children'] = []; $menuMap[$item['smid']] = $item; } // 构建树形结构 foreach($menus as $item){ if($item['parent_id'] == 0){ // 顶级菜单 $menuTree[$item['smid']] = &$menuMap[$item['smid']]; }else{ // 子菜单,添加到父菜单的children数组中 if(isset($menuMap[$item['parent_id']])){ $menuMap[$item['parent_id']]['children'][] = &$menuMap[$item['smid']]; } } } $menu = $menuTree; } View::assign([ 'role' => $role, 'menu' => $menu ]); return View::fetch(); } # 欢迎页面 public function welcome(){ try { // 获取最近7天的日期 $dates = []; for ($i = 6; $i >= 0; $i--) { $dates[] = date('Y-m-d', strtotime("-$i day")); } // 初始化数据数组 $visitData = []; $userData = []; $resourceData = []; $articleData = []; // 直接查询每天的数据 foreach ($dates as $date) { $dayStats = Db::name('daily_stats') ->where('date', $date) ->find(); // 访问数据 $visitData[] = [ 'date' => $date, 'visits' => $dayStats ? intval($dayStats['daily_visits']) : 0, 'uv' => $dayStats ? intval($dayStats['unique_visitors']) : 0 ]; // 用户数据 $userData[] = [ 'date' => $date, 'total' => $dayStats ? intval($dayStats['total_users']) : 0, 'new' => $dayStats ? intval($dayStats['new_users']) : 0 ]; // 资源数据 $resourceData[] = [ 'date' => $date, 'total' => $dayStats ? intval($dayStats['total_resources']) : 0, 'new' => $dayStats ? intval($dayStats['daily_resources']) : 0, 'downloads' => $dayStats ? intval($dayStats['resource_downloads']) : 0 ]; // 文章数据 $articleData[] = [ 'date' => $date, 'total' => $dayStats ? intval($dayStats['total_articles']) : 0, 'new' => $dayStats ? intval($dayStats['daily_articles']) : 0, 'views' => $dayStats ? intval($dayStats['article_views']) : 0 ]; } // 获取今日统计数据 $today = date('Y-m-d'); $todayStats = Db::name('daily_stats') ->where('date', $today) ->find(); // 获取最近的操作日志 $recentActivities = Db::name('logs_operation') ->field('operation_time, module, operation') ->order('operation_time DESC') ->limit(5) ->select() ->each(function($item) { $item['content'] = date('Y年m月d日 H:i:s', strtotime($item['operation_time'])) . ' 在 ' . ($item['module'] ?: '未知模块') . ' ' . ($item['operation'] ?: '未知操作'); $item['icon'] = $this->getActivityIcon($item['module'] ?: '其他'); return $item; }); // 处理图表数据 $chartData = [ 'visitTrend' => [ 'dates' => array_map(function($item) { return date('m-d', strtotime($item['date'])); }, $visitData), 'visits' => array_column($visitData, 'visits'), 'uvs' => array_column($visitData, 'uv') ], 'userGrowth' => [ 'dates' => array_map(function($item) { return date('m-d', strtotime($item['date'])); }, $userData), 'newUsers' => array_column($userData, 'new'), 'totalUsers' => array_column($userData, 'total') ], 'resourceStats' => [ 'dates' => array_map(function($item) { return date('m-d', strtotime($item['date'])); }, $resourceData), 'newResources' => array_column($resourceData, 'new'), 'totalResources' => array_column($resourceData, 'total'), 'downloads' => array_column($resourceData, 'downloads') ], 'articleStats' => [ 'dates' => array_map(function($item) { return date('m-d', strtotime($item['date'])); }, $articleData), 'newArticles' => array_column($articleData, 'new'), 'totalArticles' => array_column($articleData, 'total'), 'views' => array_column($articleData, 'views') ] ]; // 传递给视图 View::assign([ 'todayStats' => $todayStats ?: [ 'total_users' => 0, 'new_users' => 0, 'total_visits' => 0, 'daily_visits' => 0, 'unique_visitors' => 0, 'total_articles' => 0, 'daily_articles' => 0, 'article_views' => 0, 'total_resources' => 0, 'daily_resources' => 0, 'resource_downloads' => 0 ], 'recentActivities' => $recentActivities, 'chartData' => $chartData ]); return View::fetch(); } catch (\Exception $e) { // 记录错误日志 \think\facade\Log::error('获取统计数据失败:' . $e->getMessage()); // 返回空数据 View::assign([ 'todayStats' => [ 'total_users' => 0, 'new_users' => 0, 'total_visits' => 0, 'daily_visits' => 0, 'unique_visitors' => 0, 'total_articles' => 0, 'daily_articles' => 0, 'article_views' => 0, 'total_resources' => 0, 'daily_resources' => 0, 'resource_downloads' => 0 ], 'recentActivities' => [], 'chartData' => [ 'visitTrend' => ['dates' => [], 'visits' => [], 'uvs' => []], 'userGrowth' => ['dates' => [], 'newUsers' => [], 'totalUsers' => []], 'resourceStats' => ['dates' => [], 'newResources' => [], 'totalResources' => [], 'downloads' => []], 'articleStats' => ['dates' => [], 'newArticles' => [], 'totalArticles' => [], 'views' => []] ] ]); return View::fetch(); } } /** * 根据操作类型获取对应的图标 */ private function getActivityIcon($type) { $icons = [ '用户管理' => '👥', '文章管理' => '📝', '资源管理' => '📦', '系统设置' => '⚙️', '登录' => '🔑', '退出' => '🚪', '其他' => '📌' ]; return $icons[$type] ?? '📌'; } /** * 格式化访问趋势数据 */ 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 ]; } /** * 保存附件信息到数据库 * @param string $name 文件名 * @param int $type 附件类型 * @param int $size 文件大小 * @param string $src 文件路径 * @return int 附件ID */ private function saveAttachment($name, $type, $size, $src) { $data = [ 'name' => $name, 'type' => $type, 'size' => $size, 'src' => $src, 'create_time' => time(), 'update_time' => time() ]; return Attachments::insertGetId($data); } # 图片上传 public function upload_img(){ // 获取上传的文件 $file = request()->file(); $files = request()->file('file'); // 检查是否有文件上传 if(empty($file)){ return json(['code'=>1, 'msg'=>'没有文件上传'])->send(); } try { // 验证上传的文件 validate([ 'image'=>'filesize:51200|fileExt:jpg,png,gif,jpeg' ])->check($file); // 存储文件到public磁盘的uploads目录 $info = Filesystem::disk('public')->putFile('uploads', $files); // 处理文件路径,统一使用正斜杠 $info = str_replace("\\", "/", $info); $img = '/storage/'.$info; // 保存附件信息 $fileName = $files->getOriginalName(); $fileSize = $files->getSize(); $attachmentId = $this->saveAttachment($fileName, 1, $fileSize, $img); // 1: 图片 // 返回成功信息 return json([ 'code' => 0, 'data' => $img, 'url' => $this->config['admin_domain'].$img, 'attachment_id' => $attachmentId ])->send(); } catch (\think\exception\ValidateException $e) { // 捕获验证异常并返回错误信息 return json(['code'=>1, 'msg'=>$e->getMessage()])->send(); } catch (\Exception $e) { // 捕获其他异常 return json(['code'=>1, 'msg'=>'上传失败:'.$e->getMessage()])->send(); } } # 清除缓存 public function clear(){ $a = delete_dir_file(Env::get('runtime_path').'cache/'); $b = delete_dir_file(Env::get('runtime_path').'temp/'); if ($a || $b) { $this->returnCode(0, '清除缓存成功'); } else { $this->returnCode(1, '清除缓存失败'); } } # 文件上传 public function upload_file(){ $file = request()->file(); $files = request()->file('file'); if(empty($file)){ return json(['code'=>1, 'msg'=>'没有文件上传'])->send(); } try { // 只验证文件扩展名,不验证大小 validate([ 'file'=>'fileExt:doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,7z' ])->check($file); $info = Filesystem::disk('public')->putFile('uploads/files', $files); // 处理文件路径 $info = str_replace("\\", "/", $info); $filePath = '/storage/'.$info; // 保存附件信息 $fileName = $files->getOriginalName(); $fileSize = $files->getSize(); $attachmentId = $this->saveAttachment($fileName, 2, $fileSize, $filePath); // 2: 文件 return json([ 'code' => 0, 'data' => [ 'src' => $filePath, 'attachment_id' => $attachmentId ] ])->send(); } catch (\think\exception\ValidateException $e) { return json(['code'=>1, 'msg'=>$e->getMessage()])->send(); } catch (\Exception $e) { return json(['code'=>1, 'msg'=>'上传失败:'.$e->getMessage()])->send(); } } # 视频上传 public function upload_video(){ $file = request()->file(); $files = request()->file('file'); if(empty($file)){ return json(['code'=>1, 'msg'=>'没有文件上传'])->send(); } try { validate(['video'=>'filesize:102400|fileExt:mp4,avi,mov,wmv,flv'])->check($file); $info = Filesystem::disk('public')->putFile('uploads/videos', $files); // 处理文件路径 $info = str_replace("\\", "/", $info); $videoPath = '/storage/'.$info; // 保存附件信息 $fileName = $files->getOriginalName(); $fileSize = $files->getSize(); $attachmentId = $this->saveAttachment($fileName, 3, $fileSize, $videoPath); // 3: 视频 return json([ 'code' => 0, 'data' => [ 'src' => $videoPath, 'attachment_id' => $attachmentId ] ])->send(); } catch (\think\exception\ValidateException $e) { return json(['code'=>1, 'msg'=>$e->getMessage()])->send(); } } # 音频上传 public function upload_audio(){ $file = request()->file(); $files = request()->file('file'); if(empty($file)){ return json(['code'=>1, 'msg'=>'没有文件上传'])->send(); } try { validate(['audio'=>'filesize:51200|fileExt:mp3,wav,ogg,m4a'])->check($file); $info = Filesystem::disk('public')->putFile('uploads/audios', $files); // 处理文件路径 $info = str_replace("\\", "/", $info); $audioPath = '/storage/'.$info; // 保存附件信息 $fileName = $files->getOriginalName(); $fileSize = $files->getSize(); $attachmentId = $this->saveAttachment($fileName, 4, $fileSize, $audioPath); // 4: 音频 return json([ 'code' => 0, 'data' => [ 'src' => $audioPath, 'attachment_id' => $attachmentId ] ])->send(); } catch (\think\exception\ValidateException $e) { return json(['code'=>1, 'msg'=>$e->getMessage()])->send(); } } }