yunzer/app/admin/controller/IndexController.php
2025-06-07 09:15:14 +08:00

518 lines
14 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* 商业使用授权协议
*
* Copyright (c) 2025 [云泽网]. 保留所有权利.
*
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
*
* 授权购买请联系: 357099073@qq.com
* 官方网站: https://www.yunzer.cn
*
* 评估用户须知:
* 1. 禁止移除版权声明
* 2. 禁止用于生产环境
* 3. 禁止转售或分发
*/
/**
* 后台管理系统-首页
*/
namespace app\admin\controller;
use app\admin\controller\Base;
use app\admin\model\DailyStats;
use app\admin\model\Log\LogsOperation;
use app\index\model\Attachments;
use think\facade\Db;
use think\facade\View;
use think\facade\Env;
use think\facade\Config;
use app\admin\controller\Log;
use \think\facade\Filesystem;
use app\admin\model\AdminUserGroup;
use app\admin\model\AdminSysMenu;
class IndexController extends Base{
# 首页
public function index(){
$menus = [];
$menu = [];
$where = ['group_id'=>$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();
}
}
}