first commit
This commit is contained in:
@@ -0,0 +1,508 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
/**
|
||||
* 后台管理系统-文章管理
|
||||
*/
|
||||
namespace app\admin\controller;
|
||||
use app\admin\model\Article\Articles;
|
||||
use app\admin\model\Article\ArticlesCategory;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
use app\admin\controller\LogController as Log;
|
||||
use app\admin\controller\BaseController;
|
||||
|
||||
class ArticlesController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 获取控制器名称
|
||||
* @return string
|
||||
*/
|
||||
public function getControllerName()
|
||||
{
|
||||
return 'Article';
|
||||
}
|
||||
|
||||
// 文章列表
|
||||
public function articlelist()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$category = input('post.category');
|
||||
$page = intval(input('post.page', 1));
|
||||
$limit = intval(input('post.limit', 10));
|
||||
$title = input('post.title');
|
||||
$author = input('post.author');
|
||||
|
||||
$query = Articles::where('delete_time', null)
|
||||
->where('status', '<>', 3);
|
||||
|
||||
// 分类筛选
|
||||
if (!empty($category)) {
|
||||
// 先获取分类ID
|
||||
$cateInfo = ArticlesCategory::where('name', $category)
|
||||
->where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->find();
|
||||
|
||||
if ($cateInfo) {
|
||||
$query = $query->where('cate', $cateInfo['id']);
|
||||
}
|
||||
}
|
||||
|
||||
// 标题搜索
|
||||
if (!empty($title)) {
|
||||
$query = $query->where('title', 'like', '%'.$title.'%');
|
||||
}
|
||||
|
||||
// 作者搜索
|
||||
if (!empty($author)) {
|
||||
$query = $query->where('author', 'like', '%'.$author.'%');
|
||||
}
|
||||
|
||||
// 获取总记录数
|
||||
$count = $query->count();
|
||||
|
||||
// 获取分页数据
|
||||
$lists = $query->order('id DESC')
|
||||
->page($page, $limit)
|
||||
->select()
|
||||
->each(function ($item) {
|
||||
// 获取分类信息
|
||||
$cateInfo = ArticlesCategory::where('id', $item['cate'])
|
||||
->field('name, image')
|
||||
->find();
|
||||
|
||||
// 设置分类名称
|
||||
$item['cate'] = $cateInfo ? $cateInfo['name'] : '';
|
||||
|
||||
// 如果文章没有图片,使用分类的图片
|
||||
if (empty($item['image']) && $cateInfo && !empty($cateInfo['image'])) {
|
||||
$item['image'] = $cateInfo['image'];
|
||||
}
|
||||
|
||||
// 格式化时间
|
||||
$item['create_time'] = is_numeric($item['create_time']) ? date('Y-m-d H:i:s', $item['create_time']) : $item['create_time'];
|
||||
$item['publishdate'] = is_numeric($item['publishdate']) ? date('Y-m-d H:i:s', $item['publishdate']) : '';
|
||||
|
||||
return $item;
|
||||
});
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'count' => $count,
|
||||
'data' => $lists
|
||||
]);
|
||||
} else {
|
||||
// 获取所有分类并构建父子结构
|
||||
$allCategories = ArticlesCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->order('sort asc, id asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$categories = [];
|
||||
foreach ($allCategories as $category) {
|
||||
if ($category['cid'] == 0) {
|
||||
$category['children'] = [];
|
||||
foreach ($allCategories as $subCategory) {
|
||||
if ($subCategory['cid'] == $category['id']) {
|
||||
$category['children'][] = $subCategory;
|
||||
}
|
||||
}
|
||||
$categories[] = $category;
|
||||
}
|
||||
}
|
||||
|
||||
View::assign([
|
||||
'categories' => $categories
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
|
||||
// 添加文章
|
||||
public function add()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$data = [
|
||||
'title' => input('post.title'),
|
||||
'cate' => input('post.cate'),
|
||||
'image' => input('post.image'),
|
||||
'content' => input('post.content'),
|
||||
'author' => input('post.author'),
|
||||
'desc' => input('post.desc'),
|
||||
'status' => input('post.status', 2),
|
||||
'publishdate' => time(),
|
||||
'create_time' => time()
|
||||
];
|
||||
|
||||
$insert = Articles::insert($data);
|
||||
if (empty($insert)) {
|
||||
Log::record('添加文章', 0, '添加文章失败', '文章管理');
|
||||
return json(['code' => 1, 'msg' => '添加失败', 'data' => []]);
|
||||
}
|
||||
Log::record('添加文章', 1, '', '文章管理');
|
||||
return json(['code' => 0, 'msg' => '添加成功', 'data' => []]);
|
||||
} else {
|
||||
$lists = Articles::order('id DESC')
|
||||
->select()
|
||||
->each(function ($item, $key) {
|
||||
$item['create_time'] = time();
|
||||
return $item;
|
||||
});
|
||||
View::assign([
|
||||
'lists' => $lists
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑文章
|
||||
public function edit()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$id = input('get.id');
|
||||
$data = [
|
||||
'title' => input('post.title'),
|
||||
'cate' => input('post.cate'),
|
||||
'image' => input('post.image'),
|
||||
'content' => input('post.content'),
|
||||
'author' => input('post.author'),
|
||||
'desc' => input('post.desc'),
|
||||
'status' => input('post.status', 2),
|
||||
'update_time' => time()
|
||||
];
|
||||
|
||||
$update = Articles::where('id', $id)->update($data);
|
||||
if ($update === false) {
|
||||
Log::record('编辑文章', 0, '编辑文章失败', '文章管理');
|
||||
return json(['code' => 1, 'msg' => '更新失败', 'data' => []]);
|
||||
}
|
||||
Log::record('编辑文章', 1, '', '文章管理');
|
||||
return json(['code' => 0, 'msg' => '更新成功', 'data' => []]);
|
||||
} else {
|
||||
$id = input('get.id');
|
||||
$info = Articles::where('id', $id)->find();
|
||||
if ($info === null) {
|
||||
return json(['code' => 1, 'msg' => '文章不存在', 'data' => []]);
|
||||
}
|
||||
|
||||
$cates = ArticlesCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->order('sort asc, id asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$info['content'] = !empty($info['content']) ? htmlspecialchars_decode(str_replace(["\r\n", "\r", "\n"], '', addslashes($info['content']))) : '';
|
||||
|
||||
$currentCate = ArticlesCategory::where('id', $info['cate'])
|
||||
->where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->find();
|
||||
$info['cate_name'] = $currentCate ? $currentCate['name'] : '';
|
||||
|
||||
View::assign([
|
||||
'info' => $info,
|
||||
'cates' => $cates
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
|
||||
// 删除文章
|
||||
public function delete()
|
||||
{
|
||||
$id = input('post.id');
|
||||
$data = [
|
||||
'delete_time' => time(),
|
||||
];
|
||||
$delete = Articles::where('id', $id)->update($data);
|
||||
if ($delete === false) {
|
||||
Log::record('删除文章', 0, '删除文章失败', '文章管理');
|
||||
return json(['code' => 1, 'msg' => '删除失败', 'data' => []]);
|
||||
}
|
||||
Log::record('删除文章', 1, '', '文章管理');
|
||||
return json(['code' => 0, 'msg' => '删除成功', 'data' => []]);
|
||||
}
|
||||
|
||||
// 文章分类
|
||||
public function articlecate()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$lists = ArticlesCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->order('sort asc, id asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 构建树形结构
|
||||
$tree = [];
|
||||
foreach ($lists as $item) {
|
||||
if ($item['cid'] == 0) {
|
||||
$node = [
|
||||
'id' => $item['id'],
|
||||
'title' => $item['name'],
|
||||
'children' => []
|
||||
];
|
||||
|
||||
// 查找子分类
|
||||
foreach ($lists as $subItem) {
|
||||
if ($subItem['cid'] == $item['id']) {
|
||||
$node['children'][] = [
|
||||
'id' => $subItem['id'],
|
||||
'title' => $subItem['name'],
|
||||
'children' => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$tree[] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $tree]);
|
||||
}
|
||||
|
||||
// 非 POST 请求返回视图
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
//获取分类结构
|
||||
public function getcate()
|
||||
{
|
||||
// 获取所有分类
|
||||
$lists = ArticlesCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->order('sort asc, id asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 构建父子结构
|
||||
$tree = [];
|
||||
foreach ($lists as $item) {
|
||||
if ($item['cid'] == 0) {
|
||||
// 顶级分类
|
||||
$tree[] = $item;
|
||||
} else {
|
||||
// 子分类
|
||||
foreach ($tree as &$parent) {
|
||||
if ($parent['id'] == $item['cid']) {
|
||||
if (!isset($parent['children'])) {
|
||||
$parent['children'] = [];
|
||||
}
|
||||
$parent['children'][] = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $tree]);
|
||||
}
|
||||
|
||||
// 添加文章分类
|
||||
public function cateadd()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$data = [
|
||||
'name' => input('post.name'),
|
||||
'image' => input('post.image'),
|
||||
'cid' => input('post.cid'),
|
||||
'sort' => input('post.sort', 0),
|
||||
'status' => input('post.status', 1),
|
||||
'create_time' => time()
|
||||
];
|
||||
|
||||
$insert = ArticlesCategory::insert($data);
|
||||
if (empty($insert)) {
|
||||
Log::record('添加文章分类', 0, '添加文章分类失败', '文章分类');
|
||||
return json(['code' => 1, 'msg' => '添加失败', 'data' => []]);
|
||||
}
|
||||
Log::record('添加文章分类', 1, '', '文章分类');
|
||||
return json(['code' => 0, 'msg' => '添加成功', 'data' => []]);
|
||||
} else {
|
||||
// 获取所有可选的父级分类
|
||||
$parentCategories = ArticlesCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->where('cid', 0)
|
||||
->field('id, name')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'parentOptions' => $parentCategories
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
//编辑文章分类
|
||||
public function cateedit()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$data = [
|
||||
'id' => input('post.id'),
|
||||
'name' => input('post.name'),
|
||||
'image' => input('post.image'),
|
||||
'cid' => input('post.cid'),
|
||||
'sort' => input('post.sort', 0),
|
||||
'status' => input('post.status', 1),
|
||||
'update_time' => time()
|
||||
];
|
||||
|
||||
$update = ArticlesCategory::where('id', $data['id'])
|
||||
->update($data);
|
||||
|
||||
if ($update === false) {
|
||||
Log::record('编辑文章分类', 0, '更新文章分类失败', '文章分类');
|
||||
return json(['code' => 1, 'msg' => '更新失败', 'data' => []]);
|
||||
}
|
||||
Log::record('编辑文章分类', 1, '', '文章分类');
|
||||
return json(['code' => 0, 'msg' => '更新成功', 'data' => []]);
|
||||
} else {
|
||||
$id = input('get.id');
|
||||
$info = ArticlesCategory::where('id', $id)->find();
|
||||
|
||||
// 获取所有可选的父级分类
|
||||
$parentCategories = ArticlesCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->where('id', '<>', $id) // 排除自己
|
||||
->where(function ($query) use ($id) {
|
||||
// 排除自己的所有子分类
|
||||
$query->where('cid', '<>', $id);
|
||||
})
|
||||
->field('id, name, cid')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 构建父级分类选项
|
||||
$parentOptions = [];
|
||||
foreach ($parentCategories as $category) {
|
||||
if ($category['cid'] == 0) {
|
||||
$parentOptions[] = [
|
||||
'id' => $category['id'],
|
||||
'name' => $category['name']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'info' => $info,
|
||||
'parentOptions' => $parentOptions
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
//删除文章分类
|
||||
public function catedel()
|
||||
{
|
||||
$id = input('post.id');
|
||||
|
||||
// 检查是否有子分类
|
||||
$hasChildren = ArticlesCategory::where('cid', $id)
|
||||
->where('delete_time', null)
|
||||
->find();
|
||||
|
||||
if ($hasChildren) {
|
||||
Log::record('删除文章分类', 0, '该分类下有子分类,无法删除', '文章分类');
|
||||
return json(['code' => 1, 'msg' => '该分类下有子分类,无法删除', 'data' => []]);
|
||||
}
|
||||
|
||||
$delete = ArticlesCategory::where('id', $id)
|
||||
->update(['delete_time' => time()]);
|
||||
|
||||
if ($delete === false) {
|
||||
Log::record('删除文章分类', 0, '删除文章分类失败', '文章分类');
|
||||
return json(['code' => 1, 'msg' => '删除失败', 'data' => []]);
|
||||
}
|
||||
Log::record('删除文章分类', 1, '', '文章分类');
|
||||
return json(['code' => 0, 'msg' => '删除成功', 'data' => []]);
|
||||
}
|
||||
|
||||
//统计文章数量
|
||||
public function counts() {
|
||||
try {
|
||||
// 获取文章总数
|
||||
$total = Articles::where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->count();
|
||||
|
||||
// 获取今日新增文章数
|
||||
$today = strtotime(date('Y-m-d'));
|
||||
$todayNew = Articles::where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->where('create_time', '>=', $today)
|
||||
->count();
|
||||
|
||||
// 获取最近7天的文章数据
|
||||
$dates = [];
|
||||
$counts = [];
|
||||
$totalCounts = []; // 存储每天的总文章数
|
||||
$totalSoFar = 0; // 用于累计总文章数
|
||||
|
||||
for ($i = 6; $i >= 0; $i--) {
|
||||
$date = date('Y-m-d', strtotime("-$i days"));
|
||||
$start = strtotime($date);
|
||||
$end = $start + 86400;
|
||||
|
||||
// 获取当天新增文章数
|
||||
$count = Articles::where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->where('create_time', '>=', $start)
|
||||
->where('create_time', '<', $end)
|
||||
->count();
|
||||
|
||||
// 获取截至当天的总文章数
|
||||
$totalCount = Articles::where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->where('create_time', '<', $end)
|
||||
->count();
|
||||
|
||||
$dates[] = $date;
|
||||
$counts[] = $count;
|
||||
$totalCounts[] = $totalCount;
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'total' => $total,
|
||||
'todayNew' => $todayNew,
|
||||
'dates' => $dates,
|
||||
'counts' => $counts,
|
||||
'totalCounts' => $totalCounts
|
||||
]
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '获取失败:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
/**
|
||||
* 后台管理系统-管理员
|
||||
*/
|
||||
namespace app\admin\controller;
|
||||
use app\AppApi;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
use think\facade\Cookie;
|
||||
use think\facade\Config;
|
||||
|
||||
use app\admin\model\YzAdminConfig;
|
||||
|
||||
use think\exception\HttpResponseException;
|
||||
use think\facade\Request;
|
||||
use think\facade\Route;
|
||||
use think\App;
|
||||
|
||||
class Base
|
||||
{
|
||||
protected $app;
|
||||
protected $request;
|
||||
public $adminId = null;
|
||||
public $config = [];
|
||||
public $aUser = [];
|
||||
public function __construct()
|
||||
{
|
||||
date_default_timezone_set('PRC');
|
||||
# 获取配置
|
||||
$YzAdminConfig = new YzAdminConfig();
|
||||
$this->config = $YzAdminConfig->getAll();
|
||||
# 获取账户,账户判断
|
||||
$this->adminId = Cookie::get('admin_id');
|
||||
if (empty($this->adminId)) {
|
||||
header('Location:' . $this->config['admin_route'] . 'Login/index');
|
||||
exit;
|
||||
}
|
||||
$this->aUser = Db::table('yz_admin_user')->where('uid', $this->adminId)->find();
|
||||
|
||||
if (empty($this->aUser)) {
|
||||
Cookie::delete('admin_id');
|
||||
$this->error('管理员账户不存在');
|
||||
}
|
||||
if ($this->aUser['status'] != 1) {
|
||||
Cookie::delete('admin_id');
|
||||
$this->error('管理员已被禁用');
|
||||
}
|
||||
# 获取用户组权限
|
||||
$group = Db::table('yz_admin_user_group')->where(['group_id' => $this->aUser['group_id']])->find();
|
||||
if (empty($group)) {
|
||||
$this->error('对不起,您没有权限');
|
||||
}
|
||||
# 获取当前链接,查询是否有权限
|
||||
$controller = request()->controller();
|
||||
$action = request()->action();
|
||||
$key = $controller . '/' . $action;
|
||||
View::assign([
|
||||
'aUser' => $this->aUser,
|
||||
'config' => $this->config
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* 返回json对象
|
||||
*/
|
||||
protected function returnCode($code, $data = [], $count = 10)
|
||||
{
|
||||
header('Content-type:application/json');
|
||||
if ($code == 0) {
|
||||
$arr = array(
|
||||
'code' => $code,
|
||||
'msg' => '操作成功',
|
||||
'count' => $count,
|
||||
'data' => $data
|
||||
);
|
||||
} else if ($code >= 1 && $code <= 100) {
|
||||
$arr = array(
|
||||
'code' => $code,
|
||||
'msg' => $data
|
||||
);
|
||||
} else {
|
||||
$appapi = new AppApi();
|
||||
$arr = array(
|
||||
'code' => $code,
|
||||
'msg' => $appapi::errorTip($code)
|
||||
);
|
||||
}
|
||||
echo json_encode($arr);
|
||||
if ($code != 0) {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作成功跳转的快捷方法
|
||||
* @access protected
|
||||
* @param mixed $msg 提示信息
|
||||
* @return void
|
||||
*/
|
||||
protected function success($msg = '')
|
||||
{
|
||||
$result = [
|
||||
'code' => 1,
|
||||
'msg' => $msg
|
||||
];
|
||||
|
||||
$type = $this->getResponseType();
|
||||
if ($type == 'html') {
|
||||
$response = view(Config::get('app.dispatch_success_tmpl'), $result);
|
||||
} else if ($type == 'json') {
|
||||
$response = json($result);
|
||||
}
|
||||
throw new HttpResponseException($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作错误跳转的快捷方法
|
||||
* @access protected
|
||||
* @param mixed $msg 提示信息
|
||||
* @return void
|
||||
*/
|
||||
protected function error($msg = '')
|
||||
{
|
||||
$result = [
|
||||
'code' => 0,
|
||||
'msg' => $msg
|
||||
];
|
||||
$response = view(Config::get('app.dispatch_error_tmpl'), $result);
|
||||
throw new HttpResponseException($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的response 输出类型
|
||||
* @access protected
|
||||
* @return string
|
||||
*/
|
||||
protected function getResponseType()
|
||||
{
|
||||
return Request::isJson() || Request::isAjax() ? 'json' : 'html';
|
||||
}
|
||||
|
||||
public function initialize(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
|
||||
// 检查是否是直接访问具体页面
|
||||
$controller = $this->request->controller();
|
||||
$action = $this->request->action();
|
||||
|
||||
// 如果不是访问index控制器,且不是通过iframe加载,且不是ajax请求
|
||||
if (
|
||||
$controller != 'Index' &&
|
||||
!$this->request->isAjax() &&
|
||||
!$this->request->header('X-Requested-With') &&
|
||||
!$this->request->param('iframe')
|
||||
) { // 添加iframe参数检查
|
||||
|
||||
// 重定向到index页面,并带上当前页面参数
|
||||
$currentUrl = $controller . '/' . $action;
|
||||
redirect(url('index/index', ['page' => $currentUrl]))->send();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use think\exception\ValidateException;
|
||||
use think\Validate;
|
||||
|
||||
/**
|
||||
* 后台控制器基础类
|
||||
*/
|
||||
abstract class BaseController extends Base
|
||||
{
|
||||
/**
|
||||
* Request实例
|
||||
* @var \think\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* 应用实例
|
||||
* @var \think\App
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* 是否批量验证
|
||||
* @var bool
|
||||
*/
|
||||
protected $batchValidate = false;
|
||||
|
||||
/**
|
||||
* 控制器中间件
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [];
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
|
||||
// 控制器初始化
|
||||
$this->initialize($app);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function initialize(App $app)
|
||||
{
|
||||
// 注册控制器映射
|
||||
$this->registerControllerMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册控制器映射
|
||||
*/
|
||||
protected function registerControllerMap()
|
||||
{
|
||||
// 获取当前控制器类名
|
||||
$className = get_class($this);
|
||||
// 获取不带命名空间的类名
|
||||
$shortName = substr($className, strrpos($className, '\\') + 1);
|
||||
// 移除Controller后缀
|
||||
$mapName = str_replace('Controller', '', $shortName);
|
||||
|
||||
// 调试信息
|
||||
trace("Controller Mapping: {$mapName} => {$className}", 'debug');
|
||||
|
||||
// 注册控制器映射
|
||||
$this->app->route->setControllerMap($mapName, $className);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取控制器名称(移除Controller后缀)
|
||||
* @return string
|
||||
*/
|
||||
public function getControllerName()
|
||||
{
|
||||
$className = get_class($this);
|
||||
$className = substr($className, strrpos($className, '\\') + 1);
|
||||
return str_replace('Controller', '', $className);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证数据
|
||||
* @access protected
|
||||
* @param array $data 数据
|
||||
* @param string|array $validate 验证器名或者验证规则数组
|
||||
* @param array $message 提示信息
|
||||
* @param bool $batch 是否批量验证
|
||||
* @return array|string|true
|
||||
* @throws ValidateException
|
||||
*/
|
||||
protected function validate(array $data, $validate, array $message = [], bool $batch = false)
|
||||
{
|
||||
if (is_array($validate)) {
|
||||
$v = new Validate();
|
||||
$v->rule($validate);
|
||||
} else {
|
||||
if (strpos($validate, '.')) {
|
||||
// 支持场景
|
||||
[$validate, $scene] = explode('.', $validate);
|
||||
}
|
||||
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
|
||||
$v = new $class();
|
||||
if (!empty($scene)) {
|
||||
$v->scene($scene);
|
||||
}
|
||||
}
|
||||
|
||||
$v->message($message);
|
||||
|
||||
// 是否批量验证
|
||||
if ($batch || $this->batchValidate) {
|
||||
$v->batch(true);
|
||||
}
|
||||
|
||||
return $v->failException(true)->check($data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,518 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\controller\Base;
|
||||
use think\facade\Db;
|
||||
use think\facade\Request;
|
||||
use think\facade\View;
|
||||
use think\facade\Cookie;
|
||||
use app\admin\model\Log\LogsLogin;
|
||||
use app\admin\model\Log\LogsOperation;
|
||||
|
||||
class LogController extends Base
|
||||
{
|
||||
/**
|
||||
* 登录日志列表
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$page = input('post.page', 1);
|
||||
$limit = input('post.limit', 10);
|
||||
$username = input('post.username');
|
||||
$ip = input('post.ip');
|
||||
$status = input('post.status');
|
||||
$startTime = input('post.start_time');
|
||||
$endTime = input('post.end_time');
|
||||
|
||||
// 搜索条件
|
||||
if ($username) {
|
||||
$query = LogsLogin::where('username', 'like', "%{$username}%");
|
||||
}
|
||||
if ($ip) {
|
||||
$query = LogsLogin::where('ip_address', 'like', "%{$ip}%");
|
||||
}
|
||||
if ($status !== '') {
|
||||
$query = LogsLogin::where('login_status', $status);
|
||||
}
|
||||
if ($startTime) {
|
||||
$query = LogsLogin::where('login_time', '>=', $startTime);
|
||||
}
|
||||
if ($endTime) {
|
||||
$query = LogsLogin::where('login_time', '<=', $endTime);
|
||||
}
|
||||
|
||||
$count = LogsLogin::count();
|
||||
$list = LogsLogin::order('id desc')
|
||||
->page($page, $limit)
|
||||
->select();
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'count' => $count,
|
||||
'data' => $list
|
||||
]);
|
||||
}
|
||||
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作日志列表
|
||||
*/
|
||||
public function operation()
|
||||
{
|
||||
$params = input();
|
||||
$page = $params['page'] ?? 1;
|
||||
$limit = $params['limit'] ?? 10;
|
||||
|
||||
// 构建搜索条件
|
||||
$searchFields = [
|
||||
'username' => ['field' => 'username', 'type' => 'like'],
|
||||
'module' => ['field' => 'module', 'type' => 'like'],
|
||||
'operation' => ['field' => 'operation', 'type' => 'like'],
|
||||
'status' => ['field' => 'status', 'type' => '='],
|
||||
'start_time' => ['field' => 'operation_time', 'type' => '>='],
|
||||
'end_time' => ['field' => 'operation_time', 'type' => '<=']
|
||||
];
|
||||
|
||||
$query = LogsOperation::where('1=1');
|
||||
|
||||
foreach ($searchFields as $param => $config) {
|
||||
if (!empty($params[$param])) {
|
||||
$value = $params[$param];
|
||||
if ($config['type'] === 'like') {
|
||||
$value = "%{$value}%";
|
||||
}
|
||||
$query = $query->where($config['field'], $config['type'], $value);
|
||||
}
|
||||
}
|
||||
|
||||
$count = LogsOperation::where('1=1')->count();
|
||||
$list = LogsOperation::where('1=1')
|
||||
->order('id desc')
|
||||
->page($page, $limit)
|
||||
->select();
|
||||
|
||||
if (Request::isAjax()) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'count' => $count,
|
||||
'data' => $list
|
||||
]);
|
||||
}
|
||||
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录操作日志
|
||||
* @param string $operation 操作名称
|
||||
* @param int $status 状态 1成功 0失败
|
||||
* @param string $error_message 错误信息
|
||||
* @param string $module 模块名称
|
||||
*/
|
||||
public static function record($operation, $status = 1, $error_message = '', $module = '')
|
||||
{
|
||||
$data = [
|
||||
'username' => Cookie::get('admin_name') ?: '未知用户',
|
||||
'module' => $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
|
||||
];
|
||||
|
||||
LogsOperation::insert($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作日志详情
|
||||
*/
|
||||
public function getOperationDetail()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
if (!$id) {
|
||||
return json(['code' => 1, 'msg' => '参数错误']);
|
||||
}
|
||||
|
||||
$info = LogsOperation::where('id', $id)
|
||||
->find();
|
||||
|
||||
if (!$info) {
|
||||
return json(['code' => 1, 'msg' => '日志不存在']);
|
||||
}
|
||||
|
||||
// 格式化请求参数
|
||||
if (!empty($info['request_params'])) {
|
||||
$info['request_params'] = json_decode($info['request_params'], true);
|
||||
}
|
||||
|
||||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $info]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
/**
|
||||
* 后台管理系统-登录
|
||||
*/
|
||||
namespace app\admin\controller;
|
||||
use think\App;
|
||||
use app\AppApi;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
use think\facade\Cookie;
|
||||
use think\facade\Request;
|
||||
use app\admin\model\YzAdminConfig;
|
||||
use app\admin\model\AdminUser;
|
||||
use app\admin\model\Log\LogsLogin;
|
||||
|
||||
class LoginController extends Base
|
||||
{
|
||||
public $app;
|
||||
public $config;
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->config = new YzAdminConfig();
|
||||
}
|
||||
|
||||
// 登录页面
|
||||
public function index()
|
||||
{
|
||||
# 获取配置
|
||||
$config = $this->config->getAll();
|
||||
View::assign([
|
||||
'config' => $config
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
// 记录登录日志
|
||||
public function recordLoginLog($username, $status, $reason = '')
|
||||
{
|
||||
$data = [
|
||||
'username' => $username,
|
||||
'ip_address' => Request::ip(),
|
||||
'location' => $this->getLocation(Request::ip()),
|
||||
'device_type' => $this->getDeviceType(),
|
||||
'user_agent' => Request::header('user-agent'),
|
||||
'login_status' => $status,
|
||||
'failure_reason' => $reason,
|
||||
'login_time' => date('Y-m-d H:i:s')
|
||||
];
|
||||
LogsLogin::create($data);
|
||||
}
|
||||
|
||||
// 获取IP地址位置
|
||||
public function getLocation($ip)
|
||||
{
|
||||
// 这里可以接入IP地址库或第三方API
|
||||
return '未知';
|
||||
}
|
||||
|
||||
// 获取设备类型
|
||||
public function getDeviceType()
|
||||
{
|
||||
$agent = Request::header('user-agent');
|
||||
if (preg_match('/(iPhone|iPod|Android|ios|iPad|Mobile)/i', $agent)) {
|
||||
return '移动端';
|
||||
}
|
||||
return 'PC端';
|
||||
}
|
||||
|
||||
// 登录
|
||||
public function login()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$account = trim(input('post.account'));
|
||||
if (empty($account)) {
|
||||
$this->recordLoginLog($account, 0, '账号不能为空');
|
||||
return json(['code' => 1, 'msg' => '账号不能为空']);
|
||||
}
|
||||
$pattern = "/^([0-9A-Za-z-_.]+)@([0-9a-z]+.[a-z]{2,3}(.[a-z]{2})?)$/i";
|
||||
if (!preg_match($pattern, $account)) {
|
||||
$this->recordLoginLog($account, 0, '邮箱格式不正确');
|
||||
return json(['code' => 1, 'msg' => '邮箱格式不正确']);
|
||||
}
|
||||
$password = trim(input('post.password'));
|
||||
if (empty($password)) {
|
||||
$this->recordLoginLog($account, 0, '密码不能为空');
|
||||
return json(['code' => 1, 'msg' => '密码不能为空']);
|
||||
}
|
||||
$code = trim(input('post.code'));
|
||||
if ($code == '') {
|
||||
$this->recordLoginLog($account, 0, '验证码不能为空');
|
||||
return json(['code' => 1, 'msg' => '验证码不能为空']);
|
||||
}
|
||||
if (!captcha_check($code)) {
|
||||
$this->recordLoginLog($account, 0, '验证码错误');
|
||||
return json(['code' => 1, 'msg' => '验证码错误']);
|
||||
}
|
||||
$aUser = AdminUser::where('account', $account)->find();
|
||||
if (empty($aUser)) {
|
||||
$this->recordLoginLog($account, 0, '账号不存在');
|
||||
return json(['code' => 1, 'msg' => '账号不存在']);
|
||||
}
|
||||
if ($aUser['status'] != 1) {
|
||||
$this->recordLoginLog($account, 0, '账号已被禁用');
|
||||
return json(['code' => 1, 'msg' => '账号已被禁用']);
|
||||
}
|
||||
if ($aUser['password'] != md5($password)) {
|
||||
$this->recordLoginLog($account, 0, '密码错误');
|
||||
return json(['code' => 1, 'msg' => '密码错误']);
|
||||
}
|
||||
$remember = input('post.remember');
|
||||
if (!empty($remember)) {
|
||||
Cookie::set('admin_id', $aUser['uid'], 60 * 60 * 24 * 7);
|
||||
Cookie::set('admin_name', $aUser['name'], 60 * 60 * 24 * 7);
|
||||
} else {
|
||||
Cookie::set('admin_id', $aUser['uid']);
|
||||
Cookie::set('admin_name', $aUser['name']);
|
||||
}
|
||||
AdminUser::where('uid', $aUser['uid'])->update(
|
||||
['login_count' => $aUser['login_count'] + 1, 'update_time' => time()]
|
||||
);
|
||||
// 记录登录成功日志
|
||||
$this->recordLoginLog($account, 1);
|
||||
return json(['code' => 0, 'msg' => '登录成功', 'data' => []]);
|
||||
}
|
||||
}
|
||||
|
||||
// 退出
|
||||
public function logout()
|
||||
{
|
||||
Cookie::delete('admin_id');
|
||||
Cookie::delete('admin_name');
|
||||
return json(['code' => 0, 'msg' => '退出成功', 'data' => []]);
|
||||
}
|
||||
|
||||
// 密码重置页面
|
||||
public function resetpwdindex()
|
||||
{
|
||||
return View::fetch('resetpwd');
|
||||
}
|
||||
|
||||
//管理员密码重置
|
||||
public function resetpwd()
|
||||
{
|
||||
$account = trim(input('post.account'));
|
||||
if (empty($account)) {
|
||||
return json(['code' => 1, 'msg' => '账号不能为空']);
|
||||
}
|
||||
|
||||
$user = AdminUser::where('account', $account)->find();
|
||||
|
||||
if (!$user) {
|
||||
return json(['code' => 1, 'msg' => '未找到该用户名']);
|
||||
}
|
||||
|
||||
// 使用md5进行密码加密处理
|
||||
$password = md5('123456');
|
||||
|
||||
try {
|
||||
$res = AdminUser::where('account', $account)
|
||||
->update(['password' => $password]);
|
||||
|
||||
if ($res === false) {
|
||||
return json(['code' => 1, 'msg' => '数据库更新失败']);
|
||||
}
|
||||
|
||||
if ($res === 0) {
|
||||
return json(['code' => 1, 'msg' => '密码未发生变化']);
|
||||
}
|
||||
|
||||
return json(['code' => 0, 'msg' => '密码重置成功', 'data' => []]);
|
||||
} catch (\Exception $e) {
|
||||
return json(['code' => 1, 'msg' => '系统错误:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,554 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
/**
|
||||
* 后台管理系统-资源管理
|
||||
*/
|
||||
namespace app\admin\controller;
|
||||
use app\admin\controller\BaseController;
|
||||
use app\admin\model\Resource\Resource;
|
||||
use app\admin\model\Resource\ResourceCategory;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
use think\facade\Db;
|
||||
use app\admin\controller\LogController as Log;
|
||||
use think\App;
|
||||
|
||||
class ResourcesController extends BaseController
|
||||
{
|
||||
// 资源列表
|
||||
public function lists()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$params = [
|
||||
'category' => input('post.category'),
|
||||
'name' => input('post.name'),
|
||||
'uploader' => input('post.uploader')
|
||||
];
|
||||
$page = (int) input('post.page', 1);
|
||||
$limit = (int) input('post.limit', 10);
|
||||
|
||||
$query = Resource::where('delete_time', null)
|
||||
->where('status', 1);
|
||||
|
||||
// 分类筛选
|
||||
if (!empty($params['category'])) {
|
||||
$cateInfo = ResourceCategory::where('name', $params['category'])
|
||||
->where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->field('id')
|
||||
->find();
|
||||
|
||||
if ($cateInfo) {
|
||||
$query = $query->where('cate', (int) $cateInfo['id']);
|
||||
}
|
||||
}
|
||||
|
||||
// 名称搜索
|
||||
if (!empty($params['name'])) {
|
||||
$query = $query->where('name', 'like', '%' . $params['name'] . '%');
|
||||
}
|
||||
|
||||
// 上传者搜索
|
||||
if (!empty($params['uploader'])) {
|
||||
$query = $query->where('uploader', 'like', '%' . $params['uploader'] . '%');
|
||||
}
|
||||
|
||||
$count = $query->count();
|
||||
|
||||
$lists = $query->order('id DESC')
|
||||
->page($page, $limit)
|
||||
->select()
|
||||
->each(function ($item) {
|
||||
// 获取分类信息
|
||||
$cateInfo = ResourceCategory::where('id', (int) $item['cate'])
|
||||
->field('name, icon')
|
||||
->find();
|
||||
if ($cateInfo) {
|
||||
$item['cate'] = $cateInfo['name'];
|
||||
if (empty($item['icon']) && !empty($cateInfo['icon'])) {
|
||||
$item['icon'] = $cateInfo['icon'];
|
||||
}
|
||||
}
|
||||
$item['create_time'] = date('Y-m-d H:i:s', (int) $item['create_time']);
|
||||
return $item;
|
||||
});
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'count' => $count,
|
||||
'data' => $lists
|
||||
]);
|
||||
} else {
|
||||
$allCategories = ResourceCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->field('id, name, cid, icon')
|
||||
->order('sort asc, id asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$categories = $this->buildParentChild($allCategories);
|
||||
|
||||
View::assign([
|
||||
'categories' => $categories
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
|
||||
// 添加资源
|
||||
public function add()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$data = [
|
||||
'title' => input('post.title'),
|
||||
'cate' => input('post.cate'),
|
||||
'desc' => input('post.desc'),
|
||||
'icon' => input('post.icon'),
|
||||
'images' => input('post.images'),
|
||||
'url' => input('post.url'),
|
||||
'fileurl' => input('post.fileurl'),
|
||||
'code' => input('post.code'),
|
||||
'zipcode' => input('post.zipcode'),
|
||||
'uploader' => input('post.uploader'),
|
||||
'content' => input('post.content'),
|
||||
'number' => input('post.number'),
|
||||
'status' => input('post.status', 1),
|
||||
'create_time' => time()
|
||||
];
|
||||
|
||||
$insert = Resource::insert($data);
|
||||
if (empty($insert)) {
|
||||
Log::record('添加资源', 0, '添加资源失败', '资源管理');
|
||||
$this->error('添加失败');
|
||||
}
|
||||
Log::record('添加资源', 1, '', '资源管理');
|
||||
return json(['code' => 0, 'msg' => '添加成功', 'data' => []]);
|
||||
} else {
|
||||
// 获取所有分类
|
||||
$allCategories = ResourceCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->field('id, name, cid, icon, number')
|
||||
->order('sort asc, id asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$categories = $this->buildParentChild($allCategories);
|
||||
|
||||
View::assign([
|
||||
'categories' => $categories
|
||||
]);
|
||||
|
||||
return View::fetch();
|
||||
} catch (\Exception $e) {
|
||||
Log::record('添加资源页面加载', 0, $e->getMessage(), '资源管理');
|
||||
$this->error('页面加载失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑资源
|
||||
public function edit()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$data = input('post.');
|
||||
$id = input('id/d', 0);
|
||||
|
||||
if (!$id) {
|
||||
Log::record('编辑资源', 0, '参数错误', '资源管理');
|
||||
return json(['code' => 1, 'msg' => '参数错误']);
|
||||
}
|
||||
|
||||
$updateData = [
|
||||
'title' => $data['title'],
|
||||
'cate' => $data['cate'],
|
||||
'desc' => $data['desc'],
|
||||
'uploader' => $data['uploader'],
|
||||
'icon' => $data['icon'],
|
||||
'images' => $data['images'],
|
||||
'fileurl' => $data['fileurl'],
|
||||
'url' => $data['url'],
|
||||
'code' => $data['code'],
|
||||
'zipcode' => $data['zipcode'],
|
||||
'sort' => $data['sort'],
|
||||
'number' => $data['number'],
|
||||
'content' => $data['content'],
|
||||
'update_time' => time()
|
||||
];
|
||||
|
||||
$result = Resource::where('id', $id)
|
||||
->update($updateData);
|
||||
|
||||
if ($result !== false) {
|
||||
Log::record('编辑资源', 1, '', '资源管理');
|
||||
return json(['code' => 0, 'msg' => '编辑成功']);
|
||||
} else {
|
||||
Log::record('编辑资源', 0, '编辑资源失败', '资源管理');
|
||||
return json(['code' => 1, 'msg' => '编辑失败']);
|
||||
}
|
||||
}
|
||||
|
||||
$id = input('id/d', 0);
|
||||
if (!$id) {
|
||||
Log::record('编辑资源', 0, '参数错误', '资源管理');
|
||||
$this->error('参数错误');
|
||||
}
|
||||
|
||||
$resource = Resource::where('id', $id)
|
||||
->where('delete_time', null)
|
||||
->find();
|
||||
|
||||
if (!$resource) {
|
||||
Log::record('编辑资源', 0, '资源不存在', '资源管理');
|
||||
$this->error('资源不存在');
|
||||
}
|
||||
|
||||
// 处理图片路径
|
||||
if (!empty($resource['images'])) {
|
||||
$domain = request()->domain();
|
||||
$images = explode(',', $resource['images']);
|
||||
// $images = array_map(function ($image) use ($domain) {
|
||||
// return $domain . $image;
|
||||
// }, $images);
|
||||
$resource['images'] = implode(',', $images);
|
||||
}
|
||||
|
||||
View::assign('resource', $resource);
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
// 删除资源
|
||||
public function delete()
|
||||
{
|
||||
$id = input('post.id');
|
||||
$delete = Resource::where('id', $id)
|
||||
->update(['delete_time' => time()]);
|
||||
if ($delete === false) {
|
||||
Log::record('删除资源', 0, '删除资源失败', '资源管理');
|
||||
return json(['code' => 1, 'msg' => '删除失败', 'data' => []]);
|
||||
}
|
||||
Log::record('删除资源', 1, '', '资源管理');
|
||||
return json(['code' => 0, 'msg' => '删除成功', 'data' => []]);
|
||||
}
|
||||
|
||||
// 资源分类
|
||||
public function cate()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$lists = ResourceCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->order('sort asc, id asc')
|
||||
->select()
|
||||
->toArray();
|
||||
$tree = $this->buildTree($lists);
|
||||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $tree]);
|
||||
}
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
//获取分类结构
|
||||
public function getcate()
|
||||
{
|
||||
$lists = ResourceCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->order('sort asc, id asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 获取每个分类下的资源总数
|
||||
foreach ($lists as &$item) {
|
||||
if ($item['cid'] == 0) {
|
||||
// 父级分类 - 统计所有子分类的资源总数
|
||||
$childIds = ResourceCategory::where('cid', $item['id'])
|
||||
->where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->column('id');
|
||||
|
||||
$item['total'] = Resource::where('cate', 'in', array_merge([$item['id']], $childIds))
|
||||
->where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->count();
|
||||
} else {
|
||||
// 子分类 - 只统计当前分类的资源
|
||||
$item['total'] = Resource::where('cate', $item['id'])
|
||||
->where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->count();
|
||||
}
|
||||
}
|
||||
|
||||
$tree = $this->buildParentChild($lists);
|
||||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $tree]);
|
||||
}
|
||||
|
||||
// 添加资源分类
|
||||
public function cateadd()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$data = [
|
||||
'name' => input('post.name'),
|
||||
'icon' => input('post.icon'),
|
||||
'cid' => input('post.cid'),
|
||||
'number' => input('post.number'),
|
||||
'sort' => input('post.sort', 0),
|
||||
'status' => input('post.status', 1),
|
||||
'create_time' => time()
|
||||
];
|
||||
|
||||
$insert = ResourceCategory::insert($data);
|
||||
if (empty($insert)) {
|
||||
Log::record('添加资源分类', 0, '添加资源分类失败', '资源分类');
|
||||
return json(['code' => 1, 'msg' => '添加失败', 'data' => []]);
|
||||
}
|
||||
Log::record('添加资源分类', 1, '', '资源分类');
|
||||
return json(['code' => 0, 'msg' => '添加成功', 'data' => []]);
|
||||
} else {
|
||||
$parentCategories = ResourceCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->where('cid', 0)
|
||||
->field('id, name')
|
||||
->select()
|
||||
->toArray();
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'parentOptions' => $parentCategories
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
//编辑资源分类
|
||||
public function cateedit()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$data = [
|
||||
'id' => input('post.id'),
|
||||
'name' => input('post.name'),
|
||||
'icon' => input('post.icon'),
|
||||
'cid' => input('post.cid'),
|
||||
'number' => input('post.number'),
|
||||
'sort' => input('post.sort', 0),
|
||||
'status' => input('post.status', 1),
|
||||
'update_time' => time()
|
||||
];
|
||||
|
||||
$update = ResourceCategory::where('id', $data['id'])
|
||||
->update($data);
|
||||
if ($update === false) {
|
||||
Log::record('编辑资源分类', 0, '更新资源分类失败', '资源分类');
|
||||
return json(['code' => 1, 'msg' => '更新失败', 'data' => []]);
|
||||
}
|
||||
Log::record('编辑资源分类', 1, '', '资源分类');
|
||||
return json(['code' => 0, 'msg' => '更新成功', 'data' => []]);
|
||||
} else {
|
||||
$id = input('get.id');
|
||||
$info = ResourceCategory::where('id', $id)->find();
|
||||
$parentCategories = ResourceCategory::where('delete_time', null)
|
||||
->where('status', 1)
|
||||
->where('cid', 0)
|
||||
->where('id', '<>', $id)
|
||||
->field('id, name')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'info' => $info,
|
||||
'parentOptions' => $parentCategories
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
//删除资源分类
|
||||
public function catedel()
|
||||
{
|
||||
$id = input('post.id');
|
||||
|
||||
// 检查是否有子分类
|
||||
$hasChildren = ResourceCategory::where('cid', $id)
|
||||
->where('delete_time', null)
|
||||
->find();
|
||||
if ($hasChildren) {
|
||||
Log::record('删除资源分类', 0, '该分类下有子分类,无法删除', '资源分类');
|
||||
return json(['code' => 1, 'msg' => '该分类下有子分类,无法删除', 'data' => []]);
|
||||
}
|
||||
|
||||
$delete = ResourceCategory::where('id', $id)
|
||||
->update(['delete_time' => time()]);
|
||||
if ($delete === false) {
|
||||
Log::record('删除资源分类', 0, '删除资源分类失败', '资源分类');
|
||||
return json(['code' => 1, 'msg' => '删除失败', 'data' => []]);
|
||||
}
|
||||
Log::record('删除资源分类', 1, '', '资源分类');
|
||||
return json(['code' => 0, 'msg' => '删除成功', 'data' => []]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源详情
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
$id = input('id/d', 0);
|
||||
if (!$id) {
|
||||
Log::record('获取资源详情', 0, '参数错误', '资源管理');
|
||||
return json(['code' => 1, 'msg' => '参数错误']);
|
||||
}
|
||||
|
||||
$resource = Resource::where('id', $id)
|
||||
->where('delete_time', null)
|
||||
->find();
|
||||
|
||||
if (!$resource) {
|
||||
Log::record('获取资源详情', 0, '资源不存在', '资源管理');
|
||||
return json(['code' => 1, 'msg' => '资源不存在']);
|
||||
}
|
||||
|
||||
// 获取分类信息
|
||||
$cateInfo = ResourceCategory::where('id', $resource['cate'])
|
||||
->field('name')
|
||||
->find();
|
||||
|
||||
if ($cateInfo) {
|
||||
$resource['cate_name'] = $cateInfo['name'];
|
||||
}
|
||||
|
||||
Log::record('获取资源详情', 1, '', '资源管理');
|
||||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $resource]);
|
||||
}
|
||||
|
||||
//统计资源数量
|
||||
public function counts()
|
||||
{
|
||||
try {
|
||||
// 获取资源总数
|
||||
$total = Resource::where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->count();
|
||||
|
||||
// 获取今日新增资源数
|
||||
$today = strtotime(date('Y-m-d'));
|
||||
$todayNew = Resource::where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->where('create_time', '>=', $today)
|
||||
->count();
|
||||
|
||||
// 获取最近7天的资源数据
|
||||
$dates = [];
|
||||
$counts = [];
|
||||
$totalCounts = []; // 存储每天的总资源数
|
||||
|
||||
for ($i = 6; $i >= 0; $i--) {
|
||||
$date = date('Y-m-d', strtotime("-$i days"));
|
||||
$start = strtotime($date);
|
||||
$end = $start + 86400;
|
||||
|
||||
// 获取当天新增资源数
|
||||
$count = Resource::where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->where('create_time', '>=', $start)
|
||||
->where('create_time', '<', $end)
|
||||
->count();
|
||||
|
||||
// 获取截至当天的总资源数
|
||||
$totalCount = Resource::where('delete_time', null)
|
||||
->where('status', '<>', 3)
|
||||
->where('create_time', '<', $end)
|
||||
->count();
|
||||
|
||||
$dates[] = $date;
|
||||
$counts[] = $count;
|
||||
$totalCounts[] = $totalCount;
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'total' => $total,
|
||||
'todayNew' => $todayNew,
|
||||
'dates' => $dates,
|
||||
'counts' => $counts,
|
||||
'totalCounts' => $totalCounts
|
||||
]
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '获取失败:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// 构建树形结构
|
||||
private function buildTree($lists)
|
||||
{
|
||||
$tree = [];
|
||||
foreach ($lists as $item) {
|
||||
if ($item['cid'] == 0) {
|
||||
$node = [
|
||||
'id' => $item['id'],
|
||||
'title' => $item['name'],
|
||||
'children' => []
|
||||
];
|
||||
|
||||
// 查找子分类
|
||||
foreach ($lists as $subItem) {
|
||||
if ($subItem['cid'] == $item['id']) {
|
||||
$node['children'][] = [
|
||||
'id' => $subItem['id'],
|
||||
'title' => $subItem['name'],
|
||||
'children' => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$tree[] = $node;
|
||||
}
|
||||
}
|
||||
return $tree;
|
||||
}
|
||||
|
||||
// 构建父子结构
|
||||
private function buildParentChild($lists)
|
||||
{
|
||||
$tree = [];
|
||||
foreach ($lists as $item) {
|
||||
if ($item['cid'] == 0) {
|
||||
// 顶级分类
|
||||
$tree[] = $item;
|
||||
} else {
|
||||
// 子分类
|
||||
foreach ($tree as &$parent) {
|
||||
if ($parent['id'] == $item['cid']) {
|
||||
if (!isset($parent['children'])) {
|
||||
$parent['children'] = [];
|
||||
}
|
||||
$parent['children'][] = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $tree;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
/**
|
||||
* 后台管理系统-用户管理
|
||||
*/
|
||||
namespace app\admin\controller;
|
||||
use app\admin\controller\BaseController;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
use think\facade\Db;
|
||||
use app\admin\controller\Log;
|
||||
use think\App;
|
||||
use app\admin\model\User\Users;
|
||||
|
||||
|
||||
class UsersController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 统计用户数量
|
||||
*/
|
||||
public function counts()
|
||||
{
|
||||
try {
|
||||
// 统计用户总数
|
||||
$total = Users::where('delete_time', 0)
|
||||
->where('status', 1)
|
||||
->count();
|
||||
|
||||
// 获取今日新增用户数
|
||||
$today = strtotime(date('Y-m-d'));
|
||||
$todayNew = Users::where('delete_time', 0)
|
||||
->where('status', 1)
|
||||
->where('create_time', '>=', $today)
|
||||
->count();
|
||||
|
||||
// 获取最近7天的用户数据
|
||||
$dates = [];
|
||||
$counts = [];
|
||||
$totalCounts = []; // 存储每天的总用户数
|
||||
|
||||
for ($i = 6; $i >= 0; $i--) {
|
||||
$date = date('Y-m-d', strtotime("-$i days"));
|
||||
$start = strtotime($date);
|
||||
$end = $start + 86400;
|
||||
|
||||
// 获取当天新增用户数
|
||||
$count = Users::where('delete_time', 0)
|
||||
->where('status', 1)
|
||||
->where('create_time', '>=', $start)
|
||||
->where('create_time', '<', $end)
|
||||
->count();
|
||||
|
||||
// 获取截至当天的总用户数
|
||||
$totalCount = Users::where('delete_time', 0)
|
||||
->where('status', 1)
|
||||
->where('create_time', '<', $end)
|
||||
->count();
|
||||
|
||||
$dates[] = $date;
|
||||
$counts[] = $count;
|
||||
$totalCounts[] = $totalCount;
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'total' => $total,
|
||||
'todayNew' => $todayNew,
|
||||
'dates' => $dates,
|
||||
'counts' => $counts,
|
||||
'totalCounts' => $totalCounts
|
||||
]
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '获取失败:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,556 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
/**
|
||||
* 后台管理系统-核心功能
|
||||
*/
|
||||
namespace app\admin\controller;
|
||||
use app\admin\controller\Base;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
use app\admin\model\YzAdminConfig;
|
||||
use app\admin\controller\LogController as Log;
|
||||
use app\admin\model\AdminSysMenu;
|
||||
use app\admin\model\AdminUserGroup;
|
||||
use app\admin\model\AdminConfig;
|
||||
use app\admin\model\ZIconfont;
|
||||
use app\admin\model\MailConfig;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
class YunzerController extends Base
|
||||
{
|
||||
# 菜单列表
|
||||
public function menuinfo()
|
||||
{
|
||||
$lists = AdminSysMenu::where('parent_id', 0)->order('sort DESC,smid DESC')->select();
|
||||
View::assign([
|
||||
'lists' => $lists
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
# 菜单添加
|
||||
public function menuadd()
|
||||
{
|
||||
$req = request();
|
||||
if ($req->isPost()) {
|
||||
$data['label'] = trim(input('post.label'));
|
||||
if (empty($data['label'])) {
|
||||
Log::record('添加菜单', 0, '请输入菜单名称', '菜单管理');
|
||||
$this->returnCode(1, '请输入菜单名称');
|
||||
}
|
||||
$data['icon_class'] = trim(input('post.icon_class'));
|
||||
$data['sort'] = (int) trim(input('post.sort'));
|
||||
$data['status'] = (int) trim(input('post.status'));
|
||||
$data['type'] = (int) trim(input('post.type', 0));
|
||||
if ($data['type'] == 1) {
|
||||
$data['src'] = trim(input('post.src1'));
|
||||
if (empty($data['src'])) {
|
||||
Log::record('添加菜单', 0, '请输入内部跳转地址', '菜单管理');
|
||||
$this->returnCode(1, '请输入内部跳转地址');
|
||||
}
|
||||
} else if ($data['type'] == 2) {
|
||||
$data['src'] = trim(input('post.src2'));
|
||||
if (empty($data['src'])) {
|
||||
Log::record('添加菜单', 0, '请输入超链接地址', '菜单管理');
|
||||
$this->returnCode(1, '请输入超链接地址');
|
||||
}
|
||||
} else {
|
||||
$data['src'] = '';
|
||||
}
|
||||
// 保存菜单
|
||||
$res = AdminSysMenu::insert($data);
|
||||
if (!$res) {
|
||||
Log::record('添加菜单', 0, '添加菜单失败', '菜单管理');
|
||||
$this->returnCode(1, '添加菜单失败');
|
||||
}
|
||||
|
||||
// 获取新插入的菜单ID
|
||||
$newMenuId = AdminSysMenu::getLastInsID();
|
||||
|
||||
// 获取所有管理员用户组
|
||||
$adminGroups = AdminUserGroup::select();
|
||||
foreach ($adminGroups as $group) {
|
||||
// 获取现有权限
|
||||
$rights = [];
|
||||
if (!empty($group['rights'])) {
|
||||
$rights = json_decode($group['rights'], true);
|
||||
}
|
||||
|
||||
// 添加新菜单ID到权限列表
|
||||
if (!in_array($newMenuId, $rights)) {
|
||||
$rights[] = $newMenuId;
|
||||
|
||||
// 更新用户组权限
|
||||
AdminUserGroup::where('group_id', $group['group_id'])
|
||||
->update(['rights' => json_encode($rights)]);
|
||||
}
|
||||
}
|
||||
|
||||
Log::record('添加菜单', 1, '', '菜单管理');
|
||||
$this->returnCode(0);
|
||||
} else {
|
||||
$iconfont = ZIconfont::where('status', 1)->select();
|
||||
View::assign([
|
||||
'iconfont' => $iconfont
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
# 菜单修改
|
||||
public function menuedit()
|
||||
{
|
||||
$req = request();
|
||||
if ($req->isPost()) {
|
||||
$smid = (int) input('post.smid');
|
||||
$data['label'] = trim(input('post.label'));
|
||||
if (!$data['label']) {
|
||||
Log::record('编辑菜单', 0, '请输入菜单名称', '菜单管理');
|
||||
$this->returnCode(1, '请输入菜单名称');
|
||||
}
|
||||
$data['icon_class'] = trim(input('post.icon_class'));
|
||||
$data['sort'] = (int) trim(input('post.sort'));
|
||||
$data['status'] = (int) trim(input('post.status'));
|
||||
$data['type'] = (int) trim(input('post.type', 0));
|
||||
if ($data['type'] == 1) {
|
||||
$data['src'] = trim(input('post.src1'));
|
||||
if (empty($data['src'])) {
|
||||
Log::record('编辑菜单', 0, '请输入内部跳转地址', '菜单管理');
|
||||
$this->returnCode(1, '请输入内部跳转地址');
|
||||
}
|
||||
} else if ($data['type'] == 2) {
|
||||
$data['src'] = trim(input('post.src2'));
|
||||
if (empty($data['src'])) {
|
||||
Log::record('编辑菜单', 0, '请输入超链接地址', '菜单管理');
|
||||
$this->returnCode(1, '请输入超链接地址');
|
||||
}
|
||||
} else {
|
||||
$data['src'] = '';
|
||||
}
|
||||
// 保存用户
|
||||
$res = AdminSysMenu::where('smid', $smid)->update($data);
|
||||
if (!$res) {
|
||||
Log::record('编辑菜单', 0, '修改菜单失败', '菜单管理');
|
||||
$this->returnCode(1, '修改菜单失败');
|
||||
}
|
||||
Log::record('编辑菜单', 1, '', '菜单管理');
|
||||
$this->returnCode(0);
|
||||
} else {
|
||||
$smid = (int) input('get.smid');
|
||||
$lists = AdminSysMenu::where('smid', $smid)->find();
|
||||
$iconfont = ZIconfont::where('status', 1)->select();
|
||||
View::assign([
|
||||
'lists' => $lists,
|
||||
'iconfont' => $iconfont
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
# 菜单删除
|
||||
public function menudel()
|
||||
{
|
||||
$smid = (int) input('post.smid');
|
||||
$count = AdminSysMenu::where('parent_id', $smid)->count();
|
||||
if ($count > 0) {
|
||||
Log::record('删除菜单', 0, '该菜单下还有子菜单,不能删除', '菜单管理');
|
||||
$this->returnCode(1, '该菜单下还有子菜单,不能删除');
|
||||
}
|
||||
$res = AdminSysMenu::where('smid', $smid)->delete();
|
||||
if (empty($res)) {
|
||||
Log::record('删除菜单', 0, '删除菜单失败', '菜单管理');
|
||||
$this->returnCode(1, '删除菜单失败');
|
||||
}
|
||||
Log::record('删除菜单', 1, '', '菜单管理');
|
||||
$this->returnCode(0);
|
||||
}
|
||||
# 按钮管理
|
||||
public function buttoninfo()
|
||||
{
|
||||
$smid = (int) input('get.smid');
|
||||
$lists = AdminSysMenu::where('parent_id', $smid)->order('sort DESC')->select()->toArray();
|
||||
if (!empty($lists)) {
|
||||
foreach ($lists as &$v) {
|
||||
switch ($v['type']) {
|
||||
case 0:
|
||||
$v['type_name'] = '顶级菜单';
|
||||
break;
|
||||
case 1:
|
||||
$v['type_name'] = '内部跳转';
|
||||
break;
|
||||
case 2:
|
||||
$v['type_name'] = '超链接';
|
||||
break;
|
||||
default:
|
||||
$v['type_name'] = '未规划类型';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
View::assign([
|
||||
'lists' => $lists,
|
||||
'smid' => $smid
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
# 按钮添加
|
||||
public function buttonadd()
|
||||
{
|
||||
$req = request();
|
||||
if ($req->isPost()) {
|
||||
$smid = (int) input('post.smid');
|
||||
$data['label'] = trim(input('post.label'));
|
||||
if (!$data['label']) {
|
||||
Log::record('添加按钮', 0, '请输入按钮名称', '按钮管理');
|
||||
$this->returnCode(1, '请输入按钮名称');
|
||||
}
|
||||
$data['icon_class'] = trim(input('post.icon_class'));
|
||||
$data['sort'] = (int) trim(input('post.sort'));
|
||||
$data['status'] = (int) trim(input('post.status'));
|
||||
$data['type'] = (int) trim(input('post.type'));
|
||||
if (empty($data['type'])) {
|
||||
Log::record('添加按钮', 0, '请选择按钮类型', '按钮管理');
|
||||
$this->returnCode(1, '请选择按钮类型');
|
||||
}
|
||||
if ($data['type'] == 1) {
|
||||
$data['src'] = trim(input('post.src1'));
|
||||
if (empty($data['src'])) {
|
||||
Log::record('添加按钮', 0, '请输入内部跳转地址', '按钮管理');
|
||||
$this->returnCode(1, '请输入内部跳转地址');
|
||||
}
|
||||
} else if ($data['type'] == 2) {
|
||||
$data['src'] = trim(input('post.src2'));
|
||||
if (empty($data['src'])) {
|
||||
Log::record('添加按钮', 0, '请输入超链接地址', '按钮管理');
|
||||
$this->returnCode(1, '请输入超链接地址');
|
||||
}
|
||||
}
|
||||
$data['parent_id'] = $smid;
|
||||
$res = AdminSysMenu::insert($data);
|
||||
if (!$res) {
|
||||
Log::record('添加按钮', 0, '添加按钮失败', '按钮管理');
|
||||
$this->returnCode(1, '添加按钮失败');
|
||||
}
|
||||
Log::record('添加按钮', 1, '', '按钮管理');
|
||||
$this->returnCode(0);
|
||||
} else {
|
||||
$smid = (int) input('get.smid');
|
||||
$iconfont = ZIconfont::where('status', 1)->select();
|
||||
View::assign([
|
||||
'smid' => $smid,
|
||||
'iconfont' => $iconfont
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
# 按钮修改
|
||||
public function buttonedit()
|
||||
{
|
||||
$req = request();
|
||||
if ($req->isPost()) {
|
||||
$smid = (int) input('post.smid');
|
||||
$data['label'] = trim(input('post.label'));
|
||||
if (!$data['label']) {
|
||||
Log::record('编辑按钮', 0, '请输入按钮名称', '按钮管理');
|
||||
$this->returnCode(1, '请输入按钮名称');
|
||||
}
|
||||
$data['icon_class'] = trim(input('post.icon_class'));
|
||||
$data['sort'] = (int) trim(input('post.sort'));
|
||||
$data['status'] = (int) trim(input('post.status'));
|
||||
$data['type'] = (int) trim(input('post.type'));
|
||||
if (empty($data['type'])) {
|
||||
Log::record('编辑按钮', 0, '请选择按钮类型', '按钮管理');
|
||||
$this->returnCode(1, '请选择按钮类型');
|
||||
}
|
||||
if ($data['type'] == 1) {
|
||||
$data['src'] = trim(input('post.src1'));
|
||||
if (empty($data['src'])) {
|
||||
Log::record('编辑按钮', 0, '请输入内部跳转地址', '按钮管理');
|
||||
$this->returnCode(1, '请输入内部跳转地址');
|
||||
}
|
||||
} else if ($data['type'] == 2) {
|
||||
$data['src'] = trim(input('post.src2'));
|
||||
if (empty($data['src'])) {
|
||||
Log::record('编辑按钮', 0, '请输入超链接地址', '按钮管理');
|
||||
$this->returnCode(1, '请输入超链接地址');
|
||||
}
|
||||
}
|
||||
$res = AdminSysMenu::where('smid', $smid)->update($data);
|
||||
if (!$res) {
|
||||
Log::record('编辑按钮', 0, '修改按钮失败', '按钮管理');
|
||||
$this->returnCode(1, '修改按钮失败');
|
||||
}
|
||||
Log::record('编辑按钮', 1, '', '按钮管理');
|
||||
$this->returnCode(0);
|
||||
} else {
|
||||
$smid = (int) input('get.smid');
|
||||
$lists = AdminSysMenu::where('smid', $smid)->find();
|
||||
$iconfont = ZIconfont::where('status', 1)->select();
|
||||
View::assign([
|
||||
'lists' => $lists,
|
||||
'iconfont' => $iconfont
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
# 按钮删除
|
||||
public function buttondel()
|
||||
{
|
||||
$smid = (int) input('post.smid');
|
||||
$res = AdminSysMenu::where('smid', $smid)->delete();
|
||||
if (empty($res)) {
|
||||
Log::record('删除按钮', 0, '删除按钮失败', '按钮管理');
|
||||
$this->returnCode(1, '删除按钮失败');
|
||||
}
|
||||
Log::record('删除按钮', 1, '', '按钮管理');
|
||||
$this->returnCode(0);
|
||||
}
|
||||
# 配置列表
|
||||
public function configlist()
|
||||
{
|
||||
$req = request();
|
||||
if ($req->isPost()) {
|
||||
$page = (int) input('post.page', 1);
|
||||
$limit = (int) input('post.limit', $this->config['admin_page']);
|
||||
$count = AdminConfig::count();
|
||||
$lists = AdminConfig::page($page, $limit)->order('config_sort DESC,config_id DESC')->select();
|
||||
$this->returnCode(0, $lists, $count);
|
||||
} else {
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
# 配置添加
|
||||
public function configadd()
|
||||
{
|
||||
$req = request();
|
||||
if ($req->isPost()) {
|
||||
$data['config_name'] = trim(input('post.config_name'));
|
||||
if (empty($data['config_name'])) {
|
||||
Log::record('添加配置', 0, '请输入关键词', '系统配置');
|
||||
$this->returnCode(1, '请输入关键词');
|
||||
}
|
||||
$data['config_info'] = trim(input('post.config_info'));
|
||||
if (empty($data['config_info'])) {
|
||||
Log::record('添加配置', 0, '请输入作用', '系统配置');
|
||||
$this->returnCode(1, '请输入作用');
|
||||
}
|
||||
$data['config_type'] = trim(input('post.config_type'));
|
||||
$data['config_desc'] = trim(input('post.config_desc'));
|
||||
$data['config_status'] = trim(input('post.config_status'));
|
||||
$data['config_sort'] = trim(input('post.config_sort'));
|
||||
$res = AdminConfig::insert($data);
|
||||
if (empty($res)) {
|
||||
Log::record('添加配置', 0, '添加配置失败', '系统配置');
|
||||
$this->returnCode(1, '添加配置失败');
|
||||
}
|
||||
Log::record('添加配置', 1, '', '系统配置');
|
||||
$this->returnCode(0);
|
||||
} else {
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
# 配置修改
|
||||
public function configedit()
|
||||
{
|
||||
$req = request();
|
||||
if ($req->isPost()) {
|
||||
$config_id = (int) input('post.config_id');
|
||||
if (empty($config_id)) {
|
||||
Log::record('编辑配置', 0, '请选择一条数据', '系统配置');
|
||||
$this->returnCode(1, '请选择一条数据');
|
||||
}
|
||||
$data['config_name'] = trim(input('post.config_name'));
|
||||
if (empty($data['config_name'])) {
|
||||
Log::record('编辑配置', 0, '请输入关键词', '系统配置');
|
||||
$this->returnCode(1, '请输入关键词');
|
||||
}
|
||||
$data['config_info'] = trim(input('post.config_info'));
|
||||
if (empty($data['config_info'])) {
|
||||
Log::record('编辑配置', 0, '请输入作用', '系统配置');
|
||||
$this->returnCode(1, '请输入作用');
|
||||
}
|
||||
$data['config_type'] = trim(input('post.config_type'));
|
||||
$data['config_desc'] = trim(input('post.config_desc'));
|
||||
$data['config_status'] = trim(input('post.config_status'));
|
||||
$data['config_sort'] = trim(input('post.config_sort'));
|
||||
$res = AdminConfig::where('config_id', $config_id)->update($data);
|
||||
if (empty($res)) {
|
||||
Log::record('编辑配置', 0, '修改配置失败', '系统配置');
|
||||
$this->returnCode(1, '修改配置失败');
|
||||
}
|
||||
Log::record('编辑配置', 1, '', '系统配置');
|
||||
$this->returnCode(0);
|
||||
} else {
|
||||
$config_id = (int) input('get.config_id');
|
||||
$find = AdminConfig::where('config_id', $config_id)->find();
|
||||
View::assign([
|
||||
'find' => $find
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
# 配置删除
|
||||
public function configdel()
|
||||
{
|
||||
$config_id = (int) input('post.config_id');
|
||||
if (empty($config_id)) {
|
||||
Log::record('删除配置', 0, '请选择一条数据', '系统配置');
|
||||
$this->returnCode(1, '请选择一条数据');
|
||||
}
|
||||
$res = AdminConfig::where('config_id', $config_id)->delete();
|
||||
if (empty($res)) {
|
||||
Log::record('删除配置', 0, '删除配置失败', '系统配置');
|
||||
$this->returnCode(1, '删除配置失败');
|
||||
}
|
||||
Log::record('删除配置', 1, '', '系统配置');
|
||||
$this->returnCode(0);
|
||||
}
|
||||
# 配置值
|
||||
public function configvalue()
|
||||
{
|
||||
$req = request();
|
||||
if ($req->isPost()) {
|
||||
$post = input('post.');
|
||||
if (empty($post)) {
|
||||
Log::record('更新配置值', 0, '数据不能为空', '系统配置');
|
||||
$this->returnCode(1, '数据不能为空');
|
||||
}
|
||||
|
||||
// 获取所有配置项,检查 config_type 为 4 的项
|
||||
$allConfigs = AdminConfig::order('config_sort DESC,config_id')->select();
|
||||
foreach ($allConfigs as $config) {
|
||||
if ($config['config_type'] == 4) {
|
||||
$checkboxName = $config['config_name'] . '_checkbox';
|
||||
$configName = $config['config_name'];
|
||||
if (!isset($post[$checkboxName])) {
|
||||
// 复选框未选中,手动添加对应的值为 0
|
||||
$post[$configName] = 0;
|
||||
} else {
|
||||
// 复选框选中,确保值为 1
|
||||
$post[$configName] = 1;
|
||||
}
|
||||
// 移除 checkbox 字段
|
||||
unset($post[$checkboxName]);
|
||||
}
|
||||
}
|
||||
|
||||
$oConfig = new YzAdminConfig();
|
||||
$updateAll = $oConfig->updateAll($post);
|
||||
if (empty($updateAll)) {
|
||||
Log::record('更新配置值', 0, '更新配置值失败', '系统配置');
|
||||
$this->returnCode(1, '更新配置值失败');
|
||||
}
|
||||
Log::record('更新配置值', 1, '', '系统配置');
|
||||
$this->returnCode(0);
|
||||
} else {
|
||||
$lists = AdminConfig::order('config_sort DESC,config_id')->select();
|
||||
View::assign([
|
||||
'lists' => $lists
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 邮件配置
|
||||
public function mailconfig()
|
||||
{
|
||||
if (Request::isPost()) {
|
||||
$data = [
|
||||
'smtp_host' => input('post.smtp_host'),
|
||||
'smtp_port' => input('post.smtp_port'),
|
||||
'smtp_email' => input('post.smtp_email'),
|
||||
'smtp_password' => input('post.smtp_password'),
|
||||
'smtp_name' => input('post.smtp_name')
|
||||
];
|
||||
|
||||
// 验证必填字段
|
||||
if (empty($data['smtp_host']) || empty($data['smtp_port']) || empty($data['smtp_email']) || empty($data['smtp_password'])) {
|
||||
// Log::record('修改邮件配置', 0, '必填字段不能为空', '邮件配置');
|
||||
return json(['code' => 1, 'msg' => '必填字段不能为空']);
|
||||
}
|
||||
|
||||
$res = MailConfig::where('id', 1)->update($data);
|
||||
if ($res === false) {
|
||||
// Log::record('修改邮件配置', 0, '更新邮件配置失败', '邮件配置');
|
||||
return json(['code' => 1, 'msg' => '更新邮件配置失败']);
|
||||
}
|
||||
// Log::record('修改邮件配置', 1, '', '邮件配置');
|
||||
return json(['code' => 0, 'msg' => '更新成功']);
|
||||
}
|
||||
|
||||
$config = MailConfig::where('id', 1)->find();
|
||||
View::assign([
|
||||
'config' => $config
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
// 获取邮件配置
|
||||
public function getMailConfig()
|
||||
{
|
||||
$config = MailConfig::where('id', 1)->find();
|
||||
if ($config) {
|
||||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $config]);
|
||||
}
|
||||
return json(['code' => 1, 'msg' => '获取配置失败']);
|
||||
}
|
||||
|
||||
// 测试邮件配置
|
||||
public function testMailConfig()
|
||||
{
|
||||
if (!Request::isPost()) {
|
||||
return json(['code' => 1, 'msg' => '请求方法无效']);
|
||||
}
|
||||
|
||||
$email = input('post.email');
|
||||
$config = input('post.config');
|
||||
|
||||
if (empty($email) || empty($config)) {
|
||||
return json(['code' => 1, 'msg' => '参数错误']);
|
||||
}
|
||||
|
||||
try {
|
||||
// 配置邮件服务器
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->isSMTP();
|
||||
$mail->Host = $config['smtp_host'];
|
||||
$mail->Port = $config['smtp_port'];
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = $config['smtp_email'];
|
||||
$mail->Password = $config['smtp_password'];
|
||||
$mail->SMTPSecure = 'ssl';
|
||||
$mail->CharSet = 'UTF-8';
|
||||
|
||||
// 设置发件人
|
||||
$mail->setFrom($config['smtp_email'], $config['smtp_name']);
|
||||
$mail->addAddress($email);
|
||||
|
||||
// 设置邮件内容
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = '邮件配置测试';
|
||||
$mail->Body = '这是一封测试邮件,如果您收到这封邮件,说明邮件配置正确。';
|
||||
|
||||
$mail->send();
|
||||
return json(['code' => 0, 'msg' => '发送成功']);
|
||||
} catch (\Exception $e) {
|
||||
//Log::record('测试邮件配置', 0, $e->getMessage(), '邮件配置');
|
||||
return json(['code' => 1, 'msg' => '发送失败:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/**
|
||||
* 商业使用授权协议
|
||||
*
|
||||
* Copyright (c) 2025 [云泽网]. 保留所有权利.
|
||||
*
|
||||
* 本软件仅供评估使用。任何商业用途必须获得书面授权许可。
|
||||
* 未经授权商业使用本软件属于侵权行为,将承担法律责任。
|
||||
*
|
||||
* 授权购买请联系: 357099073@qq.com
|
||||
* 官方网站: https://www.yunzer.cn
|
||||
*
|
||||
* 评估用户须知:
|
||||
* 1. 禁止移除版权声明
|
||||
* 2. 禁止用于生产环境
|
||||
* 3. 禁止转售或分发
|
||||
*/
|
||||
|
||||
namespace app\admin\controller;
|
||||
use app\admin\controller\Base;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
|
||||
class Yunzertest extends Base{
|
||||
public function icon_list(){
|
||||
$lists = Db::table('yz_z_iconfont')->where('status','=',1)->select();
|
||||
View::assign([
|
||||
'lists' => $lists
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
public function test_list(){
|
||||
if(Request::isPost()){
|
||||
$count = Db::table('yz_z_test')->count();
|
||||
$page = (int)input('post.page',1);
|
||||
$limit = (int)input('post.limit',10);
|
||||
$lists = Db::table('yz_z_test')->order('test_id DESC')->page($page,$limit)->select()->each(function($item, $key){
|
||||
if($item['test_reference'] == 1){
|
||||
$item['test_reference'] = '开启';
|
||||
}else{
|
||||
$item['test_reference'] = '关闭';
|
||||
}
|
||||
$item['test_time'] = date('Y-m-d H:i:s',$item['test_time']);
|
||||
return $item;
|
||||
});
|
||||
$this->returnCode(0,$lists,$count);
|
||||
}else{
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
public function test_add(){
|
||||
if(Request::isPost()){
|
||||
$data['test_input'] = input('post.test_input');
|
||||
$data['test_reference'] = input('post.test_reference');
|
||||
$data['test_time'] = input('post.test_time');
|
||||
if(!empty($data['test_time'])){
|
||||
$data['test_time'] = strtotime($data['test_time']);
|
||||
}
|
||||
$data['test_data'] = input('post.test_data');
|
||||
$data['test_datatime'] = input('post.test_datatime');
|
||||
$data['test_img'] = input('post.test_img');
|
||||
$data['test_rich_baidu'] = input('post.test_rich_baidu');
|
||||
$data['test_url'] = input('post.test_url');
|
||||
|
||||
$insert = Db::table('yz_z_test')->insert($data);
|
||||
if(empty($insert)){
|
||||
$this->returnCode('91000001');
|
||||
}
|
||||
$this->returnCode(0);
|
||||
}else{
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
public function test_edit(){
|
||||
if(Request::isPost()){
|
||||
$test_id = input('post.test_id');
|
||||
$data['test_input'] = input('post.test_input');
|
||||
$data['test_reference'] = input('post.test_reference');
|
||||
$data['test_time'] = input('post.test_time');
|
||||
if(!empty($data['test_time'])){
|
||||
$data['test_time'] = strtotime($data['test_time']);
|
||||
}
|
||||
$data['test_data'] = input('post.test_data');
|
||||
$data['test_datatime'] = input('post.test_datatime');
|
||||
$data['test_img'] = input('post.test_img');
|
||||
$data['test_rich'] = input('post.test_rich');
|
||||
$data['test_rich_baidu'] = input('post.test_rich_baidu');
|
||||
$data['test_url'] = input('post.test_url');
|
||||
|
||||
$update = Db::table('yz_z_test')->where('test_id',$test_id)->update($data);
|
||||
if(empty($update)){
|
||||
$this->returnCode('91000002');
|
||||
}
|
||||
$this->returnCode(0);
|
||||
}else{
|
||||
$test_id = input('get.test_id');
|
||||
$find = Db::table('yz_z_test')->where('test_id',$test_id)->find();
|
||||
if(!empty($find)){
|
||||
$find['test_time'] = date('Y-m-d H:i:s',$find['test_time']);
|
||||
}
|
||||
View::assign([
|
||||
'find' => $find
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
public function test_del(){
|
||||
$test_id = (int)input('post.test_id');
|
||||
$res = Db::table('yz_z_test')->where('test_id',$test_id)->delete();
|
||||
if(empty($res)){
|
||||
$this->returnCode('91000003');
|
||||
}
|
||||
$this->returnCode(0);
|
||||
}
|
||||
public function test_static_list(){
|
||||
$lists = Db::table('yz_z_test')
|
||||
->order('test_id DESC')
|
||||
->paginate();
|
||||
View::assign([
|
||||
'lists' => $lists
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
public function test_static_add(){
|
||||
if(Request::isPost()){
|
||||
$data['test_input'] = input('post.test_input');
|
||||
$data['test_reference'] = input('post.test_reference');
|
||||
$data['test_time'] = input('post.test_time');
|
||||
if(!empty($data['test_time'])){
|
||||
$data['test_time'] = strtotime($data['test_time']);
|
||||
}
|
||||
$data['test_data'] = input('post.test_data');
|
||||
$data['test_datatime'] = input('post.test_datatime');
|
||||
$data['test_img'] = input('post.test_img');
|
||||
$data['test_rich_baidu'] = input('post.test_rich_baidu');
|
||||
$data['test_url'] = input('post.test_url');
|
||||
|
||||
$insert = Db::table('yz_z_test')->insert($data);
|
||||
if(empty($insert)){
|
||||
$this->returnCode('91000001');
|
||||
}
|
||||
$this->returnCode(0);
|
||||
}else{
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
public function test_static_edit(){
|
||||
if(Request::isPost()){
|
||||
$test_id = input('post.test_id');
|
||||
$data['test_input'] = input('post.test_input');
|
||||
$data['test_reference'] = input('post.test_reference');
|
||||
$data['test_time'] = input('post.test_time');
|
||||
if(!empty($data['test_time'])){
|
||||
$data['test_time'] = strtotime($data['test_time']);
|
||||
}
|
||||
$data['test_data'] = input('post.test_data');
|
||||
$data['test_datatime'] = input('post.test_datatime');
|
||||
$data['test_img'] = input('post.test_img');
|
||||
$data['test_rich'] = input('post.test_rich');
|
||||
$data['test_rich_baidu'] = input('post.test_rich_baidu');
|
||||
$data['test_url'] = input('post.test_url');
|
||||
|
||||
$update = Db::table('yz_z_test')->where('test_id',$test_id)->update($data);
|
||||
if(empty($update)){
|
||||
$this->returnCode('91000002');
|
||||
}
|
||||
$this->returnCode(0);
|
||||
}else{
|
||||
$test_id = input('get.test_id');
|
||||
$find = Db::table('yz_z_test')->where('test_id',$test_id)->find();
|
||||
if(!empty($find)){
|
||||
$find['test_time'] = date('Y-m-d H:i:s',$find['test_time']);
|
||||
if(!empty($find['test_img'])){
|
||||
$find['test_img_s'] = explode(';',$find['test_img']);
|
||||
}
|
||||
}
|
||||
View::assign([
|
||||
'find' => $find
|
||||
]);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user