Files
yunzer/app/admin/controller/IndexController.php
T
2025-12-23 10:06:18 +08:00

518 lines
14 KiB
PHP

<?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([
'file'=>'filesize:104857600|fileExt:jpg,png,gif,jpeg'
])->check(['file' => $files]);
// 存储文件到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();
}
}
}