请选择左侧分类或点击新增按钮
+commit 0c7237da457dd944ee3e49d87aa18e7194f3ec8b Author: 李志强 <357099073@qq.com> Date: Mon Jul 14 14:48:36 2025 +0800 first commit diff --git a/.env b/.env new file mode 100644 index 0000000..86e5f26 --- /dev/null +++ b/.env @@ -0,0 +1,17 @@ +APP_DEBUG = false + +[APP] +DEFAULT_TIMEZONE = Asia/Shanghai + +[DATABASE] +TYPE = mysql +HOSTNAME = 127.0.0.1 +DATABASE = ruankao +USERNAME = ruankao +PASSWORD = 123456 +HOSTPORT = 3306 +CHARSET = utf8 +DEBUG = true + +[LANG] +default_lang = zh-cn \ No newline at end of file diff --git a/.example.env b/.example.env new file mode 100644 index 0000000..c27f74c --- /dev/null +++ b/.example.env @@ -0,0 +1 @@ +APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai [DATABASE] TYPE = mysql HOSTNAME = 127.0.0.1 DATABASE = test USERNAME = username PASSWORD = password HOSTPORT = 3306 CHARSET = utf8 DEBUG = true [LANG] default_lang = zh-cn \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..625fcdf --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/.idea +/.vscode +/vendor +runtime +*.log +config/database.php diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..36f7b6f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,42 @@ +sudo: false + +language: php + +branches: + only: + - stable + +cache: + directories: + - $HOME/.composer/cache + +before_install: + - composer self-update + +install: + - composer install --no-dev --no-interaction --ignore-platform-reqs + - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip . + - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0" + - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0" + - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip . + +script: + - php think unit + +deploy: + provider: releases + api_key: + secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw= + file: + - ThinkPHP_Core.zip + - ThinkPHP_Full.zip + skip_cleanup: true + on: + tags: true diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..15dc9c3 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,41 @@ +云泽网商业软件许可证协议 +版本 1.0 - 2025年 + +版权所有 (c) 2025 云泽网。保留所有权利。 + +重要提示:在使用本软件前,请仔细阅读以下条款和条件。下载、安装或使用本软件即表示您同意受本协议的约束。 + +1. 授权范围 +1.1 本软件仅供评估和测试目的使用,不得用于任何商业用途。 +1.2 任何商业用途(包括但不限于生产环境使用、商业服务提供、商业产品集成等)必须获得云泽网的书面授权许可。 + +2. 限制条款 +2.1 禁止移除、修改或隐藏任何版权声明、商标标识或专有权利通知。 +2.2 禁止将本软件用于生产环境或任何可能产生商业收益的场景。 +2.3 禁止对本软件进行转售、分发、出租、出借或再许可。 +2.4 禁止对本软件进行反向工程、反编译或反汇编。 + +3. 商业授权 +3.1 商业用户需通过官方渠道购买商业授权许可证。 +3.2 商业授权将提供: + - 合法的商业使用权利 + - 正式的技术支持服务 + - 软件更新和维护 +3.3 授权购买请联系:357099073@qq.com +3.4 官方网站:https://www.yunzer.cn + +4. 免责声明 +4.1 本软件按"原样"提供,不作任何明示或暗示的保证。 +4.2 在任何情况下,云泽网不对因使用或不能使用本软件所发生的特殊、附带、间接或结果性损害承担任何责任。 + +5. 违约与终止 +5.1 如违反本协议任何条款,您的使用权利将自动终止。 +5.2 云泽网保留对任何未经授权商业使用行为追究法律责任的权利。 + +6. 其他条款 +6.1 本协议受中华人民共和国法律管辖。 +6.2 云泽网保留随时修改本协议条款的权利,修改后的协议将在官方网站公布后生效。 + +如需商业使用授权,请通过以下方式联系我们: +电子邮件:357099073@qq.com +官方网站:https://www.yunzer.cn \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..dee8da3 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# phpAdmin 后台管理 (admin-thinkphp-Layui2) + +- [官网:http://www.yunzer.cn](http://www.yunzer.cn) +- [演示:admin-thinkphp-layui](admin-thinkphp-layui) + +## 一、介绍 + +- phpAdmin 后台管理 + +- [admin-thinkphp-layui] + - 后端框架:Thinkphp6.1 + - Layui2.8 + +## 二、安装教程 + +- [根据 Thinkphp6 安装](https://www.kancloud.cn/manual/thinkphp6_0/1037479) +- 伪静态 +``` +location ~* (runtime|application)/{ + return 403; +} +location / { + if (!-e $request_filename){ + rewrite ^(.*)$ /index.php?s=$1 last; break; + } +} +``` + +## 三、使用说明 + +- 1、域名指向 public 目录下 +- 2、后台管理系统访问网址:http://www.xxx.com/index.php/bews/index/index + +## 四、鸣谢 + +- [PHP 中文网](https://www.php.cn) +- [Thinkphp](http://www.thinkphp.cn) +- [Layui](https://layui.dev) + +## 五、技术支持 + +- QQ:357099073 diff --git a/app/.htaccess b/app/.htaccess new file mode 100644 index 0000000..3418e55 --- /dev/null +++ b/app/.htaccess @@ -0,0 +1 @@ +deny from all \ No newline at end of file diff --git a/app/AppApi.php b/app/AppApi.php new file mode 100644 index 0000000..ffdbe81 --- /dev/null +++ b/app/AppApi.php @@ -0,0 +1,55 @@ + '系统错误,请稍后重试', + #############系统后台使用############## + '90000001' => '管理员账户不能为空', + '90000002' => '真实姓名不能为空', + '90000003' => '手机号不能为空', + '90000004' => '角色不能为空', + '90000005' => '密码不能为空', + '90000006' => '管理员账户要用邮箱', + '90000007' => '管理员账户已存在', + '90000008' => '角色名称不能为空', + '90000009' => '导航名称不能为空', + '90000010' => '导航下还有数据', + '90000011' => '请选择类型', + '90000012' => '内部代码不能为空', + '90000013' => '链接地址不能为空', + '90000015' => '按钮名称不能为空', + '90000029' => '管理员账户不存在', + '90000030' => '管理员已被禁用', + '90000031' => '密码不正确', + + '91000001' => '添加失败', + '91000002' => '修改失败', + '91000003' => '删除失败', + '91000004' => '未改变数据', + '91000005' => '未查询到数据', + '91000006' => '失败', + ); + return $array[$code]; + } +} \ No newline at end of file diff --git a/app/AppService.php b/app/AppService.php new file mode 100644 index 0000000..7d58313 --- /dev/null +++ b/app/AppService.php @@ -0,0 +1,39 @@ +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() + ]); + } + } +} \ No newline at end of file diff --git a/app/admin/controller/Base.php b/app/admin/controller/Base.php new file mode 100644 index 0000000..b912c9a --- /dev/null +++ b/app/admin/controller/Base.php @@ -0,0 +1,181 @@ +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; + } + } +} \ No newline at end of file diff --git a/app/admin/controller/BaseController.php b/app/admin/controller/BaseController.php new file mode 100644 index 0000000..52a4f16 --- /dev/null +++ b/app/admin/controller/BaseController.php @@ -0,0 +1,149 @@ +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); + } + +} \ No newline at end of file diff --git a/app/admin/controller/IndexController.php b/app/admin/controller/IndexController.php new file mode 100644 index 0000000..0c14dd8 --- /dev/null +++ b/app/admin/controller/IndexController.php @@ -0,0 +1,518 @@ +$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(); + } + } + +} \ No newline at end of file diff --git a/app/admin/controller/LogController.php b/app/admin/controller/LogController.php new file mode 100644 index 0000000..349cdbc --- /dev/null +++ b/app/admin/controller/LogController.php @@ -0,0 +1,177 @@ +=', $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]); + } +} \ No newline at end of file diff --git a/app/admin/controller/LoginController.php b/app/admin/controller/LoginController.php new file mode 100644 index 0000000..775df20 --- /dev/null +++ b/app/admin/controller/LoginController.php @@ -0,0 +1,195 @@ +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()]); + } + } + +} \ No newline at end of file diff --git a/app/admin/controller/ResourcesController.php b/app/admin/controller/ResourcesController.php new file mode 100644 index 0000000..1c32770 --- /dev/null +++ b/app/admin/controller/ResourcesController.php @@ -0,0 +1,554 @@ + 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; + } +} \ No newline at end of file diff --git a/app/admin/controller/UsersController.php b/app/admin/controller/UsersController.php new file mode 100644 index 0000000..8c0bf1c --- /dev/null +++ b/app/admin/controller/UsersController.php @@ -0,0 +1,98 @@ +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() + ]); + } + } +} \ No newline at end of file diff --git a/app/admin/controller/YunzerController.php b/app/admin/controller/YunzerController.php new file mode 100644 index 0000000..166d665 --- /dev/null +++ b/app/admin/controller/YunzerController.php @@ -0,0 +1,556 @@ +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()]); + } + } +} \ No newline at end of file diff --git a/app/admin/controller/YunzeradminController.php b/app/admin/controller/YunzeradminController.php new file mode 100644 index 0000000..b35ea19 --- /dev/null +++ b/app/admin/controller/YunzeradminController.php @@ -0,0 +1,1209 @@ + $group + ]); + return View::fetch(); + } + + // 角色添加 + public function groupadd() + { + if (Request::isPost()) { + $data['group_name'] = trim(input('post.group_name')); + if (!$data['group_name']) { + Log::record('添加角色', 0, '角色名称不能为空', '角色管理'); + return json(['code' => 1, 'msg' => '角色名称不能为空']); + } + $data['status'] = intval(trim(input('post.status'))); + $data['create_time'] = time(); + $menus = input('post.menu/a'); + if ($menus) { + $data['rights'] = json_encode(array_keys($menus)); + } + $res = AdminUserGroup::insert($data); + if (!$res) { + Log::record('添加角色', 0, '添加角色失败', '角色管理'); + return json(['code' => 1, 'msg' => '添加角色失败']); + } + Log::record('添加角色', 1, '', '角色管理'); + return json(['code' => 0, 'msg' => '添加成功']); + } else { + $menus = AdminSysMenu::order('type,sort desc')->where('status', '=', 1)->select(); + $menu = []; + + // 先处理所有父菜单 + foreach ($menus as $menus_v) { + if ($menus_v['parent_id'] == 0) { + $menu[$menus_v['smid']] = $menus_v; + $menu[$menus_v['smid']]['children'] = []; // 初始化 children 数组 + } + } + + // 再处理子菜单 + foreach ($menus as $menus_v) { + if ($menus_v['parent_id'] != 0 && isset($menu[$menus_v['parent_id']])) { + $menu[$menus_v['parent_id']]['children'][] = $menus_v; + } + } + + View::assign([ + 'menus' => $menu + ]); + return View::fetch(); + } + } + + // 角色编辑 + public function groupedit() + { + if (Request::isPost()) { + $group_id = (int) trim(input('post.group_id')); + $data['group_name'] = trim(input('post.group_name')); + if (!$data['group_name']) { + Log::record('编辑角色', 0, '角色名称不能为空', '角色管理'); + return json(['code' => 1, 'msg' => '角色名称不能为空']); + } + $data['status'] = (int) trim(input('post.status')); + $menus = input('post.menu/a'); + if ($menus) { + $data['rights'] = json_encode(array_keys($menus)); + } else { + $data['rights'] = ''; + } + $res = AdminUserGroup::where('group_id', $group_id)->update($data); + if (!$res) { + Log::record('编辑角色', 0, '更新角色失败', '角色管理'); + return json(['code' => 1, 'msg' => '更新角色失败']); + } + Log::record('编辑角色', 1, '', '角色管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } else { + $group_id = (int) input('get.group_id'); + $group = AdminUserGroup::where('group_id', $group_id)->find(); + if ($group && $group['rights']) { + $group['rights'] = json_decode($group['rights']); + } + + // 使用模型中的 getMenuTree 方法获取菜单树 + $menu = AdminSysMenu::getMenuTree(); + + View::assign([ + 'group' => $group, + 'menus' => $menu + ]); + return View::fetch(); + } + } + + // 角色删除 + public function groupdel() + { + $group_id = (int) input('post.group_id'); + $res = AdminUserGroup::where('group_id', $group_id)->delete(); + if (empty($res)) { + Log::record('删除角色', 0, '删除角色失败', '角色管理'); + return json(['code' => 1, 'msg' => '删除角色失败']); + } + Log::record('删除角色', 1, '', '角色管理'); + return json(['code' => 0, 'msg' => '删除成功']); + } + + // 管理员列表 + public function userinfo() + { + $lists = AdminUser::select(); + $group = []; + $groups = AdminUserGroup::select(); + foreach ($groups as $key => $value) { + $group[$value['group_id']] = $value; + } + View::assign([ + 'lists' => $lists, + 'group' => $group + ]); + return View::fetch(); + } + + // 管理员添加 + public function useradd() + { + if (Request::isPost()) { + $data['account'] = trim(input('post.account')); + if (empty($data['account'])) { + Log::record('添加管理员', 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, $data['account'])) { + Log::record('添加管理员', 0, '邮箱格式不正确', '管理员管理'); + return json(['code' => 1, 'msg' => '邮箱格式不正确']); + } + $item = AdminUser::where('account', $data['account'])->find(); + if ($item) { + Log::record('添加管理员', 0, '该账号已存在', '管理员管理'); + return json(['code' => 1, 'msg' => '该账号已存在']); + } + $data['name'] = trim(input('post.name')); + $data['phone'] = trim(input('post.phone')); + $data['qq'] = (int) trim(input('post.qq')); + $data['group_id'] = (int) input('post.group_id'); + $data['sex'] = (int) (input('post.sex')); + $data['status'] = (int) (input('post.status')); + $password = trim(input('post.password')); + if (empty($data['name'])) { + Log::record('添加管理员', 0, '姓名不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '姓名不能为空']); + } + if (empty($data['phone'])) { + Log::record('添加管理员', 0, '手机号不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '手机号不能为空']); + } + if (empty($data['group_id'])) { + Log::record('添加管理员', 0, '请选择角色', '管理员管理'); + return json(['code' => 1, 'msg' => '请选择角色']); + } + if (empty($password)) { + Log::record('添加管理员', 0, '密码不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '密码不能为空']); + } else { + $data['password'] = md5($password); + } + $data['create_time'] = time(); + $data['update_time'] = time(); + $res = AdminUser::insert($data); + if (!$res) { + Log::record('添加管理员', 0, '添加管理员失败', '管理员管理'); + return json(['code' => 1, 'msg' => '添加管理员失败']); + } + Log::record('添加管理员', 1, '', '管理员管理'); + return json(['code' => 0, 'msg' => '添加成功']); + } else { + $group = []; + $groups = AdminUserGroup::select(); + foreach ($groups as $key => $value) { + $group[$value['group_id']] = $value; + } + View::assign([ + 'group' => $group + ]); + return View::fetch(); + } + } + + // 管理员编辑 + public function useredit() + { + if (Request::isPost()) { + $uid = (int) trim(input('post.uid')); + $data['name'] = trim(input('post.name')); + $data['phone'] = trim(input('post.phone')); + $data['qq'] = (int) trim(input('post.qq')); + $data['group_id'] = (int) input('post.group_id'); + $data['sex'] = (int) (input('post.sex')); + $data['status'] = (int) (input('post.status')); + if (empty($data['name'])) { + Log::record('编辑管理员', 0, '姓名不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '姓名不能为空']); + } + if (empty($data['phone'])) { + Log::record('编辑管理员', 0, '手机号不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '手机号不能为空']); + } + if (empty($data['group_id'])) { + Log::record('编辑管理员', 0, '请选择角色', '管理员管理'); + return json(['code' => 1, 'msg' => '请选择角色']); + } + $res = AdminUser::where('uid', $uid)->update($data); + if (!$res) { + Log::record('编辑管理员', 0, '更新管理员信息失败', '管理员管理'); + return json(['code' => 1, 'msg' => '更新管理员信息失败']); + } + Log::record('编辑管理员', 1, '', '管理员管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } else { + $uid = (int) input('get.uid'); + // 加载管理员 + $lists = AdminUser::where('uid', $uid)->find(); + // 加载角色 + $group = []; + $groups = AdminUserGroup::select(); + foreach ($groups as $key => $value) { + $group[$value['group_id']] = $value; + } + View::assign([ + 'lists' => $lists, + 'group' => $group + ]); + return View::fetch(); + } + } + + // 管理员删除 + public function userdel() + { + $uid = (int) input('post.uid'); + $res = AdminUser::where('uid', $uid)->delete(); + if (empty($res)) { + Log::record('删除管理员', 0, '删除管理员失败', '管理员管理'); + return json(['code' => 1, 'msg' => '删除管理员失败']); + } + Log::record('删除管理员', 1, '', '管理员管理'); + return json(['code' => 0, 'msg' => '删除成功']); + } + + // 管理员信息 + public function admininfo() + { + if (Request::isPost()) { + $find = AdminUser::where('uid', $this->adminId)->find(); + if (empty($find)) { + Log::record('修改个人信息', 0, '当前账户不存在', '个人信息'); + return json(['code' => 1, 'msg' => '当前账户不存在']); + } + $data['name'] = trim(input('post.name')); + $data['phone'] = trim(input('post.phone')); + $data['qq'] = (int) trim(input('post.qq')); + $data['sex'] = (int) (input('post.sex')); + if (empty($data['name'])) { + Log::record('修改个人信息', 0, '姓名不能为空', '个人信息'); + return json(['code' => 1, 'msg' => '姓名不能为空']); + } + if (empty($data['phone'])) { + Log::record('修改个人信息', 0, '手机号不能为空', '个人信息'); + return json(['code' => 1, 'msg' => '手机号不能为空']); + } + + // 处理密码修改 + $old_pw = trim(input('post.old_pw')); + $new_pw = trim(input('post.new_pw')); + if (!empty($old_pw) && !empty($new_pw)) { + if (md5($old_pw) != $find['password']) { + Log::record('修改个人信息', 0, '原密码错误', '个人信息'); + return json(['code' => 1, 'msg' => '原密码错误']); + } + $data['password'] = md5($new_pw); + } + + $res = AdminUser::where('uid', $this->adminId)->update($data); + if (!$res) { + Log::record('修改个人信息', 0, '更新管理员信息失败', '个人信息'); + return json(['code' => 1, 'msg' => '更新管理员信息失败']); + } + Log::record('修改个人信息', 1, '', '个人信息'); + return json(['code' => 0, 'msg' => '更新成功']); + } else { + return View::fetch(); + } + } + + // 前端会员列表 + public function frontuser() + { + $lists = Users::select(); + $group = []; + $groups = UsersGroup::select(); + foreach ($groups as $key => $value) { + $group[$value['group_id']] = $value['group_name']; + } + // 替换 group_id 为 group_name + foreach ($lists as &$user) { + $gid = $user['group_id'] ?? 0; + $user['group_id'] = isset($group[$gid]) ? $group[$gid] : ''; + } + unset($user); + if (request()->isAjax()) { + return json([ + 'code' => 0, + 'msg' => '', + 'count' => count($lists), + 'data' => $lists + ]); + } + View::assign([ + 'lists' => $lists, + 'group' => $group + ]); + return View::fetch(); + } + + // 前端会员添加 + public function frontuseradd() + { + if (Request::isPost()) { + $data['account'] = trim(input('post.account')); + if (empty($data['account'])) { + Log::record('添加管理员', 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, $data['account'])) { + Log::record('添加管理员', 0, '邮箱格式不正确', '管理员管理'); + return json(['code' => 1, 'msg' => '邮箱格式不正确']); + } + $item = Users::where('account', $data['account'])->find(); + if ($item) { + Log::record('添加管理员', 0, '该账号已存在', '管理员管理'); + return json(['code' => 1, 'msg' => '该账号已存在']); + } + $data['name'] = trim(input('post.name')); + $data['phone'] = trim(input('post.phone')); + $data['qq'] = (int) trim(input('post.qq')); + $data['group_id'] = (int) input('post.group_id'); + $data['sex'] = (int) (input('post.sex')); + $data['status'] = (int) (input('post.status')); + $password = trim(input('post.password')); + if (empty($data['name'])) { + Log::record('添加管理员', 0, '姓名不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '姓名不能为空']); + } + if (empty($data['phone'])) { + Log::record('添加管理员', 0, '手机号不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '手机号不能为空']); + } + if (empty($data['group_id'])) { + Log::record('添加管理员', 0, '请选择角色', '管理员管理'); + return json(['code' => 1, 'msg' => '请选择角色']); + } + if (empty($password)) { + Log::record('添加管理员', 0, '密码不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '密码不能为空']); + } else { + $data['password'] = md5($password); + } + $data['create_time'] = time(); + $data['update_time'] = time(); + $res = Users::insert($data); + if (!$res) { + Log::record('添加管理员', 0, '添加管理员失败', '管理员管理'); + return json(['code' => 1, 'msg' => '添加管理员失败']); + } + Log::record('添加管理员', 1, '', '管理员管理'); + return json(['code' => 0, 'msg' => '添加成功']); + } else { + $group = []; + $groups = UsersGroup::select(); + foreach ($groups as $key => $value) { + $group[$value['group_id']] = $value; + } + View::assign([ + 'group' => $group + ]); + return View::fetch(); + } + } + + // 前端会员编辑 + public function frontuseredit() + { + if (Request::isPost()) { + $uid = (int) trim(input('post.uid')); + $data['name'] = trim(input('post.name')); + $data['phone'] = trim(input('post.phone')); + $data['qq'] = (int) trim(input('post.qq')); + $data['group_id'] = (int) input('post.group_id'); + $data['sex'] = (int) (input('post.sex')); + $data['status'] = (int) (input('post.status')); + if (empty($data['name'])) { + Log::record('编辑管理员', 0, '姓名不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '姓名不能为空']); + } + if (empty($data['phone'])) { + Log::record('编辑管理员', 0, '手机号不能为空', '管理员管理'); + return json(['code' => 1, 'msg' => '手机号不能为空']); + } + if (empty($data['group_id'])) { + Log::record('编辑管理员', 0, '请选择角色', '管理员管理'); + return json(['code' => 1, 'msg' => '请选择角色']); + } + $res = Users::where('uid', $uid)->update($data); + if (!$res) { + Log::record('编辑管理员', 0, '更新管理员信息失败', '管理员管理'); + return json(['code' => 1, 'msg' => '更新管理员信息失败']); + } + Log::record('编辑管理员', 1, '', '管理员管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } else { + $uid = (int) input('get.uid'); + // 加载前端会员 + $lists = Users::where('uid', $uid)->find(); + // 加载角色 + $group = []; + $groups = UsersGroup::select(); + foreach ($groups as $key => $value) { + $group[$value['group_id']] = $value; + } + View::assign([ + 'lists' => $lists, + 'group' => $group + ]); + return View::fetch(); + } + } + + // 前端会员删除 + public function frontuserdel() + { + $uid = (int) input('post.uid'); + $res = Users::where('uid', $uid)->delete(); + if (empty($res)) { + Log::record('删除管理员', 0, '删除管理员失败', '管理员管理'); + return json(['code' => 1, 'msg' => '删除管理员失败']); + } + Log::record('删除管理员', 1, '', '管理员管理'); + return json(['code' => 0, 'msg' => '删除成功']); + } + + // 前端会员信息 + public function frontuserdetail() + { + if (Request::isPost()) { + $find = Users::where('uid', $this->adminId)->find(); + if (empty($find)) { + Log::record('修改个人信息', 0, '当前账户不存在', '个人信息'); + return json(['code' => 1, 'msg' => '当前账户不存在']); + } + $data['name'] = trim(input('post.name')); + $data['phone'] = trim(input('post.phone')); + $data['qq'] = (int) trim(input('post.qq')); + $data['sex'] = (int) (input('post.sex')); + if (empty($data['name'])) { + Log::record('修改个人信息', 0, '姓名不能为空', '个人信息'); + return json(['code' => 1, 'msg' => '姓名不能为空']); + } + if (empty($data['phone'])) { + Log::record('修改个人信息', 0, '手机号不能为空', '个人信息'); + return json(['code' => 1, 'msg' => '手机号不能为空']); + } + + // 处理密码修改 + $old_pw = trim(input('post.old_pw')); + $new_pw = trim(input('post.new_pw')); + if (!empty($old_pw) && !empty($new_pw)) { + if (md5($old_pw) != $find['password']) { + Log::record('修改个人信息', 0, '原密码错误', '个人信息'); + return json(['code' => 1, 'msg' => '原密码错误']); + } + $data['password'] = md5($new_pw); + } + + $res = Users::where('uid', $this->adminId)->update($data); + if (!$res) { + Log::record('修改个人信息', 0, '更新管理员信息失败', '个人信息'); + return json(['code' => 1, 'msg' => '更新管理员信息失败']); + } + Log::record('修改个人信息', 1, '', '个人信息'); + return json(['code' => 0, 'msg' => '更新成功']); + } else { + return View::fetch(); + } + } + + //banner管理 + public function banner() + { + return View::fetch(); + } + + // banner列表 + public function bannerlist() + { + if (Request::isGet()) { + $page = intval(input('post.page', 1)); + $limit = intval(input('post.limit', 10)); + + $query = Banner::where('delete_time', null) + ->field('id, title, image, url, sort, create_time, update_time'); + + // 获取总记录数 + $count = $query->count(); + + // 获取分页数据 + $lists = $query->order(['sort DESC', 'id DESC']) + ->page($page, $limit) + ->select() + ->toArray(); + + // 处理数据 + foreach ($lists as &$item) { + $item['create_time'] = is_numeric($item['create_time']) ? date('Y-m-d H:i:s', $item['create_time']) : $item['create_time']; + $item['update_time'] = is_numeric($item['update_time']) ? date('Y-m-d H:i:s', $item['update_time']) : $item['update_time']; + } + + return json([ + 'code' => 0, + 'msg' => '', + 'count' => $count, + 'data' => $lists + ]); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 添加banner + public function banneradd() + { + if (Request::isPost()) { + $data = [ + 'title' => input('post.title'), + 'image' => input('post.image'), + 'url' => input('post.url'), + 'sort' => input('post.sort', 0), + 'status' => 1, + 'create_time' => time() + ]; + + $res = Banner::insert($data); + if (!$res) { + Log::record('添加Banner', 0, '添加Banner失败', 'Banner管理'); + return json(['code' => 1, 'msg' => '添加Banner失败']); + } + Log::record('添加Banner', 1, '', 'Banner管理'); + return json(['code' => 0, 'msg' => '添加成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 编辑banner + public function banneredit() + { + if (Request::isPost()) { + $id = input('post.id'); + if (empty($id)) { + Log::record('编辑Banner', 0, 'ID不能为空', 'Banner管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $data = [ + 'title' => input('post.title'), + 'image' => input('post.image'), + 'url' => input('post.url'), + 'sort' => input('post.sort', 0), + 'update_time' => time() + ]; + + $res = Banner::where('id', $id)->update($data); + if ($res === false) { + Log::record('编辑Banner', 0, '更新Banner失败', 'Banner管理'); + return json(['code' => 1, 'msg' => '更新Banner失败']); + } + Log::record('编辑Banner', 1, '', 'Banner管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 删除banner + public function bannerdel() + { + if (Request::isPost()) { + $id = input('post.id'); + if (empty($id)) { + Log::record('删除Banner', 0, 'ID不能为空', 'Banner管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $res = Banner::where('id', $id)->update(['delete_time' => time()]); + if (!$res) { + Log::record('删除Banner', 0, '删除Banner失败', 'Banner管理'); + return json(['code' => 1, 'msg' => '删除Banner失败']); + } + Log::record('删除Banner', 1, '', 'Banner管理'); + return json(['code' => 0, 'msg' => '删除成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 修改banner状态 + public function bannerstatus() + { + if (Request::isPost()) { + $id = input('post.id'); + $status = input('post.status'); + + if (empty($id)) { + Log::record('修改Banner状态', 0, 'ID不能为空', 'Banner管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $res = Banner::where('id', $id)->update(['status' => $status]); + if ($res === false) { + Log::record('修改Banner状态', 0, '更新状态失败', 'Banner管理'); + return json(['code' => 1, 'msg' => '更新状态失败']); + } + Log::record('修改Banner状态', 1, '', 'Banner管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + //内容推送 + public function contentpush() + { + return View::fetch(); + } + + // 内容推送列表 + public function contentpushlist() + { + if (Request::isGet()) { + // 获取分页参数 + $page = (int) input('get.page', 1); + $limit = (int) input('get.limit', 10); + + // 1. 获取 Articles 表(delete_time为空,status=2) + $articles = Articles::where('delete_time', null) + ->where('status', 2) + ->field('id, title, push, create_time') + ->select() + ->toArray(); + foreach ($articles as &$a) { + $a['type'] = 'article'; + $a['create_time'] = is_numeric($a['create_time']) ? date('Y-m-d H:i:s', $a['create_time']) : $a['create_time']; + } + unset($a); + + // 2. 获取 Resource 表(delete_time为空,status=1) + $resources = Resource::where('delete_time', null) + ->where('status', 1) + ->field('id, title, push, create_time') + ->select() + ->toArray(); + foreach ($resources as &$r) { + $r['type'] = 'resource'; + $r['create_time'] = is_numeric($r['create_time']) ? date('Y-m-d H:i:s', $r['create_time']) : $r['create_time']; + } + unset($r); + + // 3. 合并 + $lists = array_merge($articles, $resources); + + // 4. 优先显示push为0的数据,再按create_time倒序排序 + usort($lists, function ($a, $b) { + // push为0的排在前面 + if ($a['push'] != $b['push']) { + return $a['push'] - $b['push']; + } + // push相同则按create_time倒序 + return strtotime($b['create_time']) <=> strtotime($a['create_time']); + }); + + // 5. 分页 + $total = count($lists); + $offset = ($page - 1) * $limit; + $data = array_slice($lists, $offset, $limit); + + return json([ + 'code' => 0, + 'msg' => '', + 'count' => $total, + 'data' => $data + ]); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 添加内容推送 + public function contentpushadd() + { + if (Request::isPost()) { + $data = [ + 'title' => input('post.title'), + 'content' => input('post.content'), + 'image' => input('post.image'), + 'url' => input('post.url'), + 'type' => input('post.type', 1), + 'status' => input('post.status', 1), + 'sort' => input('post.sort', 0), + 'create_time' => time() + ]; + + $res = ContentPush::insert($data); + if (!$res) { + Log::record('添加内容推送', 0, '添加内容推送失败', '内容推送管理'); + return json(['code' => 1, 'msg' => '添加内容推送失败']); + } + Log::record('添加内容推送', 1, '', '内容推送管理'); + return json(['code' => 0, 'msg' => '添加成功']); + } else { + return View::fetch(); + } + } + + // 编辑内容推送 + public function contentpushedit() + { + if (Request::isPost()) { + $id = input('post.id'); + if (empty($id)) { + Log::record('编辑内容推送', 0, 'ID不能为空', '内容推送管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $data = [ + 'title' => input('post.title'), + 'content' => input('post.content'), + 'image' => input('post.image'), + 'url' => input('post.url'), + 'type' => input('post.type', 1), + 'status' => input('post.status', 1), + 'sort' => input('post.sort', 0), + 'update_time' => time() + ]; + + $res = ContentPush::where('id', $id)->update($data); + if ($res === false) { + Log::record('编辑内容推送', 0, '更新内容推送失败', '内容推送管理'); + return json(['code' => 1, 'msg' => '更新内容推送失败']); + } + Log::record('编辑内容推送', 1, '', '内容推送管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 删除内容推送 + public function contentpushdel() + { + if (Request::isPost()) { + $id = input('post.id'); + if (empty($id)) { + Log::record('删除内容推送', 0, 'ID不能为空', '内容推送管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $res = ContentPush::where('id', $id)->update(['delete_time' => time()]); + if (!$res) { + Log::record('删除内容推送', 0, '删除内容推送失败', '内容推送管理'); + return json(['code' => 1, 'msg' => '删除内容推送失败']); + } + Log::record('删除内容推送', 1, '', '内容推送管理'); + return json(['code' => 0, 'msg' => '删除成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 修改内容推送状态 + public function contentpushstatus() + { + if (Request::isPost()) { + $id = input('post.id'); + $status = input('post.status'); + + if (empty($id)) { + Log::record('修改内容推送状态', 0, 'ID不能为空', '内容推送管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $res = ContentPush::where('id', $id)->update(['status' => $status]); + if ($res === false) { + Log::record('修改内容推送状态', 0, '更新状态失败', '内容推送管理'); + return json(['code' => 1, 'msg' => '更新状态失败']); + } + Log::record('修改内容推送状态', 1, '', '内容推送管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + //推送配置列表(渲染列表) + public function contentpushsetting() + { + if (Request::isAjax() || Request::isPost()) { + $page = intval(input('get.page', 1)); + $limit = intval(input('get.limit', 10)); + + $query = ContentPushSetting::where('delete_time', null) + ->field('id, title, value, platformType, status, sort, create_time'); + + $count = $query->count(); + + $lists = $query->order(['sort' => 'DESC', 'id' => 'DESC']) + ->page($page, $limit) + ->select() + ->toArray(); + + foreach ($lists as &$item) { + $item['create_time'] = is_numeric($item['create_time']) ? date('Y-m-d H:i:s', $item['create_time']) : $item['create_time']; + } + + return json([ + 'code' => 0, + 'msg' => '获取成功', + 'count' => $count, + 'data' => $lists + ]); + } else { + return View::fetch(); + } + } + + //选择列出推送内容列表 + public function selectpushcontent() + { + $pushcate = strtolower(trim(input('get.pushcate', ''))); + $where = ['push' => 0]; + + $modelMap = [ + 'article' => Articles::class, + 'resource' => Resource::class, + ]; + + if (!isset($modelMap[$pushcate])) { + return json(['code' => 1, 'msg' => '参数错误: pushcate']); + } + + $model = $modelMap[$pushcate]; + + $query = $model::where($where)->field('title,id'); + $count = $query->count(); + $list = $query->order('id', 'desc')->select()->toArray(); + + // 判断是接口请求还是页面请求 + if (request()->isAjax() || request()->isJson()) { + return json([ + 'code' => 0, + 'msg' => '获取成功', + 'count' => $count, + 'data' => $list + ]); + } else { + // 这里传递变量到模板 + return View::fetch('', [ + 'data' => $list + ]); + } + } + + //推送配置添加和编辑通用方法 + public function contentpushsettingadd() + { + if (Request::isPost()) { + $params = input('post.'); + $id = isset($params['id']) ? intval($params['id']) : 0; + + if ($id > 0) { + // 编辑 + $res = ContentPushSetting::update($params, ['id' => $id]); + if ($res === false) { + Log::record('编辑推送配置', 0, '编辑推送配置失败', '推送配置管理'); + return json(['code' => 1, 'msg' => '编辑推送配置失败']); + } + Log::record('编辑推送配置', 1, '', '推送配置管理'); + return json(['code' => 0, 'msg' => '编辑成功']); + } else { + // 添加 + $res = ContentPushSetting::create($params); + if (!$res) { + Log::record('添加推送配置', 0, '添加推送配置失败', '推送配置管理'); + return json(['code' => 1, 'msg' => '添加推送配置失败']); + } + Log::record('添加推送配置', 1, '', '推送配置管理'); + return json(['code' => 0, 'msg' => '添加成功']); + } + } else { + $id = input('get.id', 0); + $info = []; + if ($id) { + $info = ContentPushSetting::where('id', $id)->find(); + if ($info) { + $info = $info->toArray(); + } + } + return View::fetch('', ['info' => $info]); + } + } + + //推送配置软删除 + public function contentpushsettingdel() + { + if (Request::isPost()) { + $id = intval(input('post.id', 0)); + if (!$id) { + return json(['code' => 1, 'msg' => '参数错误']); + } + $setting = ContentPushSetting::where('id', $id)->find(); + if (!$setting) { + return json(['code' => 1, 'msg' => '配置不存在']); + } + $res = ContentPushSetting::where('id', $id)->update(['delete_time' => date('Y-m-d H:i:s')]); + if ($res === false) { + Log::record('删除推送配置', 0, '删除失败', '推送配置管理'); + return json(['code' => 1, 'msg' => '删除失败']); + } + Log::record('删除推送配置', 1, '', '推送配置管理'); + return json(['code' => 0, 'msg' => '删除成功']); + } + return json(['code' => 1, 'msg' => '请求方式错误']); + } + + //素材中心 + public function materialcenter() + { + return View::fetch(); + } + // 内容推送列表 + public function materialcenterlist() + { + if (Request::isGet()) { + $page = intval(input('post.page', 1)); + $limit = intval(input('post.limit', 10)); + + $query = ContentPush::where('delete_time', null) + ->field('id, title, type, status, sort, create_time, update_time'); + + // 获取总记录数 + $count = $query->count(); + + // 获取分页数据 + $lists = $query->order(['sort DESC', 'id DESC']) + ->page($page, $limit) + ->select() + ->toArray(); + + // 处理数据 + foreach ($lists as &$item) { + $item['create_time'] = is_numeric($item['create_time']) ? date('Y-m-d H:i:s', $item['create_time']) : $item['create_time']; + $item['update_time'] = is_numeric($item['update_time']) ? date('Y-m-d H:i:s', $item['update_time']) : $item['update_time']; + } + + return json([ + 'code' => 0, + 'msg' => '', + 'count' => $count, + 'data' => $lists + ]); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + // 添加内容推送 + public function materialcenteradd() + { + if (Request::isPost()) { + $data = [ + 'title' => input('post.title'), + 'content' => input('post.content'), + 'image' => input('post.image'), + 'url' => input('post.url'), + 'type' => input('post.type', 1), + 'status' => input('post.status', 1), + 'sort' => input('post.sort', 0), + 'create_time' => time() + ]; + + $res = ContentPush::insert($data); + if (!$res) { + Log::record('添加内容推送', 0, '添加内容推送失败', '内容推送管理'); + return json(['code' => 1, 'msg' => '添加内容推送失败']); + } + Log::record('添加内容推送', 1, '', '内容推送管理'); + return json(['code' => 0, 'msg' => '添加成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 编辑内容推送 + public function materialcenteredit() + { + if (Request::isPost()) { + $id = input('post.id'); + if (empty($id)) { + Log::record('编辑内容推送', 0, 'ID不能为空', '内容推送管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $data = [ + 'title' => input('post.title'), + 'content' => input('post.content'), + 'image' => input('post.image'), + 'url' => input('post.url'), + 'type' => input('post.type', 1), + 'status' => input('post.status', 1), + 'sort' => input('post.sort', 0), + 'update_time' => time() + ]; + + $res = ContentPush::where('id', $id)->update($data); + if ($res === false) { + Log::record('编辑内容推送', 0, '更新内容推送失败', '内容推送管理'); + return json(['code' => 1, 'msg' => '更新内容推送失败']); + } + Log::record('编辑内容推送', 1, '', '内容推送管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 删除内容推送 + public function materialcenterdel() + { + if (Request::isPost()) { + $id = input('post.id'); + if (empty($id)) { + Log::record('删除内容推送', 0, 'ID不能为空', '内容推送管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $res = ContentPush::where('id', $id)->update(['delete_time' => time()]); + if (!$res) { + Log::record('删除内容推送', 0, '删除内容推送失败', '内容推送管理'); + return json(['code' => 1, 'msg' => '删除内容推送失败']); + } + Log::record('删除内容推送', 1, '', '内容推送管理'); + return json(['code' => 0, 'msg' => '删除成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + // 修改内容推送状态 + public function materialcenterstatus() + { + if (Request::isPost()) { + $id = input('post.id'); + $status = input('post.status'); + + if (empty($id)) { + Log::record('修改内容推送状态', 0, 'ID不能为空', '内容推送管理'); + return json(['code' => 1, 'msg' => 'ID不能为空']); + } + + $res = ContentPush::where('id', $id)->update(['status' => $status]); + if ($res === false) { + Log::record('修改内容推送状态', 0, '更新状态失败', '内容推送管理'); + return json(['code' => 1, 'msg' => '更新状态失败']); + } + Log::record('修改内容推送状态', 1, '', '内容推送管理'); + return json(['code' => 0, 'msg' => '更新成功']); + } + return json(['code' => 1, 'msg' => '请求方法无效']); + } + + + public function gopush() + { + $platformType = input('post.platformType'); + $urls = input('post.urls/a', []); + + if (empty($platformType)) { + return json(['code' => 1, 'msg' => '平台参数缺失']); + } + if (empty($urls)) { + return json(['code' => 1, 'msg' => '推送内容url为空']); + } + + // 查找推送平台配置 + $setting = ContentPushSetting::where('platformType', $platformType)->find(); + if (!$setting) { + return json(['code' => 1, 'msg' => '未找到该平台的推送配置']); + } + if ($setting['status'] == 0) { + return json(['code' => 1, 'msg' => '该平台推送已禁用']); + } + $api = $setting['value']; + if (empty($api)) { + return json(['code' => 1, 'msg' => '推送API地址未配置']); + } + + // 推送 + $ch = curl_init(); + $options = array( + CURLOPT_URL => $api, + CURLOPT_POST => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POSTFIELDS => implode("\n", $urls), // 多行文本,每行一个url + CURLOPT_HTTPHEADER => array('Content-Type: text/plain'), + ); + curl_setopt_array($ch, $options); + $result = curl_exec($ch); + $error = curl_error($ch); + curl_close($ch); + + if ($error) { + return json(['code' => 1, 'msg' => $error, 'result' => $result]); + } + + // 解析推送返回结果 + $resultArr = json_decode($result, true); + + // 判断返回是否有error字段 + if (is_array($resultArr) && isset($resultArr['error'])) { + return json([ + 'code' => 1, + 'msg' => '推送失败: ' . (isset($resultArr['message']) ? $resultArr['message'] : '未知错误'), + 'result' => $resultArr + ]); + } + + // 判断是否有success字段,只有有success字段才认为推送成功 + if (is_array($resultArr) && isset($resultArr['success'])) { + // 推送成功后,更新对应数据的push字段为1 + // 解析urls,分别更新Articles或Resource表 + foreach ($urls as $url) { + // 匹配文章 + if (preg_match('/\/index\/articles\/detail\?id=(\d+)/', $url, $matches)) { + $id = intval($matches[1]); + if ($id > 0) { + Articles::where('id', $id)->update(['push' => 1]); + } + } + // 匹配资源 + elseif (preg_match('/\/index\/resources\/detail\?id=(\d+)/', $url, $matches)) { + $id = intval($matches[1]); + if ($id > 0) { + Resource::where('id', $id)->update(['push' => 1]); + } + } + } + return json(['code' => 0, 'msg' => '推送成功', 'result' => $resultArr]); + } else { + // 没有success字段,视为推送失败,把失败的result反馈给前端 + return json([ + 'code' => 1, + 'msg' => '推送失败', + 'result' => $resultArr !== null ? $resultArr : $result + ]); + } + } + + +} \ No newline at end of file diff --git a/app/admin/controller/Yunzertest.php b/app/admin/controller/Yunzertest.php new file mode 100644 index 0000000..ebc5b7a --- /dev/null +++ b/app/admin/controller/Yunzertest.php @@ -0,0 +1,184 @@ +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(); + } + } +} \ No newline at end of file diff --git a/app/admin/model/AdminConfig.php b/app/admin/model/AdminConfig.php new file mode 100644 index 0000000..bd6216b --- /dev/null +++ b/app/admin/model/AdminConfig.php @@ -0,0 +1,25 @@ +order('type', 'asc') + ->order('sort', 'desc') + ->select() + ->toArray(); + + $menuTree = []; + + // 先处理所有父菜单 + foreach ($menus as $menu) { + if ($menu['parent_id'] == 0) { + $menuTree[$menu['smid']] = $menu; + $menuTree[$menu['smid']]['children'] = []; + } + } + + // 再处理子菜单 + foreach ($menus as $menu) { + if ($menu['parent_id'] != 0 && isset($menuTree[$menu['parent_id']])) { + $menuTree[$menu['parent_id']]['children'][] = $menu; + } + } + + return array_values($menuTree); + } +} diff --git a/app/admin/model/AdminUser.php b/app/admin/model/AdminUser.php new file mode 100644 index 0000000..dc1d6aa --- /dev/null +++ b/app/admin/model/AdminUser.php @@ -0,0 +1,25 @@ + logs($data,$fileName); + } + } + $info = ['data'=>$data]; + $content = json_encode($info, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL; + if(empty($fileName)){ + $filePath = $path . "/" . date("Ymd",time()).'.info.log'; + }else{ + $filePath = $path . "/" . $fileName . '.info.log'; + } + $time = "[".date("Y-m-d H:i:s",time())."]"; + $re = file_put_contents($filePath, $time." ".$content , FILE_APPEND); + if(!$re){ + $this -> logs($data,$fileName); + }else{ + return true; + } + } +} \ No newline at end of file diff --git a/app/admin/model/ContentPush/ContentPush.php b/app/admin/model/ContentPush/ContentPush.php new file mode 100644 index 0000000..652375d --- /dev/null +++ b/app/admin/model/ContentPush/ContentPush.php @@ -0,0 +1,34 @@ +order('config_sort DESC')->select()->toArray(); + if(empty($aList)){ + return []; + }else{ + $return = []; + foreach($aList as $k=>$v){ + $return[$v['config_name']] = $v['config_value']; + } + } + return $return; + } + + /** + * 多条数据更新 + */ + public function updateAll($data){ + $lists = static::order('config_sort DESC,config_id')->select()->toArray(); + if(empty($lists)){ + return false; + }else{ + foreach($lists as &$lists_v){ + $lists_v['config_value'] = $data[$lists_v['config_name']]; + } + $save = static::saveAll($lists); + if(empty($save)){ + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/app/admin/model/ZIconfont.php b/app/admin/model/ZIconfont.php new file mode 100644 index 0000000..419ae18 --- /dev/null +++ b/app/admin/model/ZIconfont.php @@ -0,0 +1,25 @@ + +
请选择左侧分类或点击新增按钮
+今天是 ,祝您工作愉快
+