706 Commits

Author SHA1 Message Date
JaguarJack
068234b57c update:auth增加忽略密码验证,适配第三方登陆 2021-01-27 14:01:17 +08:00
JaguarJack
dc1ce92194 update 2021-01-24 20:27:27 +08:00
JaguarJack
937e1745d2 update:更新默认加载commands 2021-01-24 20:24:43 +08:00
JaguarJack
9f6f02ad24 update:更新上传路由 2021-01-20 20:30:04 +08:00
JaguarJack
340e8c356b fixed:捕获异常以Json方式返回 2021-01-20 20:12:08 +08:00
JaguarJack
65d3111e65 fixed:修复oss上传 2021-01-20 20:09:06 +08:00
JaguarJack
22a8574824 fixed:空值配置无法更新 2021-01-20 19:53:19 +08:00
JaguarJack
584477f711 update:更新包 2021-01-20 19:20:09 +08:00
JaguarJack
2ae7efce04 add:新增初始化管理密码命令 2021-01-20 19:19:28 +08:00
JaguarJack
b12edc9439 update:更新调度 2021-01-18 09:29:02 +08:00
JaguarJack
c02297ab91 更新:支持app commands 自动载入 2021-01-17 20:51:05 +08:00
JaguarJack
b2b6dbd5ed Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2021-01-17 11:22:13 +08:00
JaguarJack
3f154e5fb5 更新:定时任务重新修改 2021-01-17 11:21:52 +08:00
JaguarJack
cff7b38058 update:开启短线重连 2021-01-17 11:17:37 +08:00
JaguarJack
849493eea2 add:新增请求过滤空值方法 2021-01-17 09:39:18 +08:00
JaguarJack
8cace712ae update readme 2020-12-27 13:20:44 +08:00
JaguarJack
b44c8838c4 add:新增隐藏字段功能 2020-12-27 12:33:30 +08:00
JaguarJack
901c7f6cd7 update:更新定时任务搜索 2020-12-26 22:27:06 +08:00
JaguarJack
870e81ab9d add:新增快速搜索 2020-12-26 22:26:36 +08:00
JaguarJack
d4ec2d104f fixed:修改命令行无法生成model field 2020-12-26 20:56:10 +08:00
JaguarJack
614448d07a update:更新监控路由 2020-12-26 20:54:34 +08:00
JaguarJack
dcbe82f398 fixed:修复创建模块 2020-12-13 10:16:46 +08:00
JaguarJack
afe70d39b9 fixed:修复CatchJoin无法连接同一个模型两次 2020-12-13 10:16:28 +08:00
JaguarJack
9118e07d7b fixed 2020-12-04 21:09:50 +08:00
JaguarJack
c0f05fcf8f fixed:模型生成数据库字段注释标记错误 2020-12-01 17:58:53 +08:00
JaguarJack
35445f37e1 fixed:模型name属性多加了表前缀 2020-12-01 17:55:36 +08:00
JaguarJack
94c430f491 update 2020-11-29 09:29:14 +08:00
JaguarJack
97efb82971 update:强制依赖jwt包 2020-11-29 09:18:07 +08:00
JaguarJack
5f49a22a5e add:新增用户token字段 2020-11-23 19:57:49 +08:00
JaguarJack
85f4fc0df8 update:个人信息校验邮箱唯一性 2020-11-21 20:07:36 +08:00
JaguarJack
04a7818608 fixed bug 2020-11-21 12:33:55 +08:00
JaguarJack
21c1df4f69 update:class增加when方法 2020-11-19 19:11:18 +08:00
JaguarJack
0dfe4fb5c6 fixed 2020-11-19 17:44:11 +08:00
JaguarJack
9ca1fd42ae update 2020-11-19 17:31:57 +08:00
JaguarJack
5713d12ce1 updae:基于AST重构代码生成 2020-11-19 17:31:31 +08:00
JaguarJack
e01790aa23 update:composer新增查找package方法 2020-11-19 17:31:04 +08:00
JaguarJack
ecf0970ca4 fixed:修复搜索参数值为0时导致搜索错误 2020-11-19 17:30:30 +08:00
JaguarJack
78e782dd01 fixed:云上传配置无法生效 2020-11-19 09:42:54 +08:00
JaguarJack
e4a5ae0c37 add:新增创建模块 2020-11-14 18:24:33 +08:00
JaguarJack
c8e9e6361c add:新增字段自增/减少方法 2020-11-04 14:09:23 +08:00
JaguarJack
7c4fa5c516 update:优化用户的部门搜索,减少SQL 2020-11-04 10:06:23 +08:00
JaguarJack
97b7f73ff2 add:新增模型获取所有子节点方法 2020-11-04 10:05:50 +08:00
JaguarJack
0b5c883012 update:支持无限级部门搜索 2020-11-04 08:20:15 +08:00
JaguarJack
a9671b6227 update:更新路由 2020-11-03 08:12:10 +08:00
JaguarJack
9ab22b1a1c update:移除角色与部门关联 2020-10-29 08:13:20 +08:00
JaguarJack
a931b7597c update:升级tp核心 2020-10-29 08:01:27 +08:00
JaguarJack
4506219fb2 update:优化auth认证 2020-10-26 19:09:28 +08:00
JaguarJack
91a1d253c5 update:更新request验证 2020-10-26 11:20:42 +08:00
JaguarJack
3d58942844 fixed:SQL解析错误 2020-10-23 15:45:47 +08:00
JaguarJack
e0b2aafd2c update:readme 2020-10-21 18:21:21 +08:00
JaguarJack
7278be4e49 add:新增模型数据缓存 2020-10-21 17:23:22 +08:00
JaguarJack
a62020650c add:新增模型导出 2020-10-21 13:54:55 +08:00
JaguarJack
9baadccfbb add:新增Collection toTree方法 2020-10-21 08:12:07 +08:00
JaguarJack
538006c3c6 update:rewrite request post,自动填入 creator_id 数据 2020-10-15 10:00:35 +08:00
JaguarJack
e2399b6aa6 add:新增域名管理权限 2020-10-14 20:58:34 +08:00
JaguarJack
c5aee52667 update:更新附件删除 2020-10-14 20:17:18 +08:00
JaguarJack
8991315888 add:新增忽略ssl方法 2020-10-14 20:07:36 +08:00
JaguarJack
9754a23360 update:初始化数据更新 2020-10-12 19:24:51 +08:00
JaguarJack
753f6b9dcf fixed:模块列表排除超级管理员 2020-10-12 14:15:41 +08:00
JaguarJack
bcb96cd3c4 update:更新模块列表 2020-10-12 14:00:40 +08:00
JaguarJack
3908c26e2c add:新增GET方法单独的认证标识 2020-10-12 12:22:05 +08:00
JaguarJack
f17570deef uodate:数据获取用户角色,无需用户传参 2020-10-12 10:18:51 +08:00
JaguarJack
390fc8ccd5 update:更新路由 2020-09-29 14:43:07 +08:00
JaguarJack
4d9f57a8c7 update:修改操作日志搜索 2020-09-29 14:34:11 +08:00
JaguarJack
b8e08eac96 update:升级框架至6.0.4 2020-09-29 14:33:45 +08:00
JaguarJack
bece4dac86 delete:冗余模块 2020-09-28 11:14:02 +08:00
JaguarJack
4b8d5aa507 add:域名管理 2020-09-28 09:55:30 +08:00
JaguarJack
5ec24ae9c9 update:模块配置加载 2020-09-26 15:11:50 +08:00
JaguarJack
25c5faf440 add:域名管理first commit 2020-09-26 15:10:41 +08:00
JaguarJack
097b0e1ee5 fixed:登录日志删除失败 2020-09-25 10:47:20 +08:00
JaguarJack
09b20c255b Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2020-09-25 07:31:04 +08:00
JaguarJack
a3db671328 update:更新服务监控配置至模块内 2020-09-25 07:30:49 +08:00
JaguarJack
33177f26cb update:新增登录日志搜索 2020-09-24 12:19:41 +08:00
JaguarJack
45712076d2 fixed:模块Json文件无法写入 2020-09-23 08:05:31 +08:00
JaguarJack
5979088144 add:新增服务缓存,提高性能 2020-09-22 11:14:51 +08:00
JaguarJack
42e6cd36aa update:优化登录 2020-09-22 11:13:53 +08:00
JaguarJack
08b3e472a9 upate:支持增量权限菜单倒入 2020-09-21 16:14:27 +08:00
JaguarJack
42b99dd64c 更新README 2020-09-21 09:17:25 +08:00
JaguarJack
e412fd3b60 add:新增表单构建器 2020-09-21 09:16:12 +08:00
JaguarJack
4f0c37d281 add:新增用户信息编辑 2020-09-21 08:06:24 +08:00
JaguarJack
bae186d82a fixed:用户请求 2020-09-20 12:05:19 +08:00
JaguarJack
5223997031 update:优化定时任务日志记录 2020-09-20 09:50:48 +08:00
JaguarJack
5fa20a4f28 update:更新初始化密码 2020-09-19 21:17:41 +08:00
JaguarJack
0cd799dce3 update:默认模块排序 2020-09-19 16:10:08 +08:00
JaguarJack
72a878ed30 update:sms初始化关闭 2020-09-19 16:07:54 +08:00
JaguarJack
5f65e3d25f fixed:定时任务不执行 2020-09-19 16:07:32 +08:00
JaguarJack
66ec4f174d fixed:修复验证消息没有按设置提示 2020-09-18 18:53:46 +08:00
JaguarJack
64ab5439a6 升级composer.json 2020-09-17 21:22:23 +08:00
JaguarJack
0558764093 update:readme 2020-09-17 21:22:11 +08:00
JaguarJack
4216a48907 update:更新代码生成 2020-09-17 21:15:24 +08:00
JaguarJack
8b65690450 update:更新删除方法 2020-09-17 21:14:34 +08:00
JaguarJack
4f461bb673 add:新增短信平台管理 2020-09-17 21:14:00 +08:00
JaguarJack
e30de13d35 update:修改指令 2020-09-17 15:17:22 +08:00
JaguarJack
c72943da58 update:更新定时任务配置和初始化数据 2020-09-16 10:14:27 +08:00
JaguarJack
a98fbdc7a1 add:新增定时任务基类 2020-09-16 10:08:05 +08:00
JaguarJack
42ffcb75c7 update:更新whereLike查询 2020-09-16 10:07:34 +08:00
JaguarJack
c74c3c23d4 add:新增监控模块 2020-09-16 10:06:20 +08:00
JaguarJack
5211d29c5e update readme 2020-09-14 10:07:03 +08:00
JaguarJack
82dc1ebd05 update:更新初始化数据 2020-09-13 11:16:16 +08:00
JaguarJack
e35532850d update:更新微信菜单 2020-09-13 11:13:09 +08:00
JaguarJack
0da4627217 update:微信回复 2020-09-13 10:05:22 +08:00
JaguarJack
5fd218d26a update:更新模块管理 2020-09-12 18:35:31 +08:00
JaguarJack
ee624300b6 新增模块管理 2020-09-12 17:22:43 +08:00
JaguarJack
dc4855f5c1 fixed:数据字典分页查询 2020-09-12 11:11:59 +08:00
JaguarJack
9e13a9c937 upadte:优化路由写入 2020-09-11 18:19:06 +08:00
JaguarJack
90990f8782 update:微信模块初始化未安装状态 2020-09-11 07:43:44 +08:00
JaguarJack
40276babfb update:更新安装&新增本地模块安装 2020-09-11 07:42:38 +08:00
JaguarJack
818ffb2ce6 fixed:修复异常code 2020-09-09 11:35:01 +08:00
JaguarJack
763a05fa80 update:优化登录 2020-09-09 10:40:44 +08:00
JaguarJack
8c153cce60 update:转换路径 2020-09-08 19:54:05 +08:00
JaguarJack
93b6f1e2f1 fixed:数据字典分页 2020-09-08 19:36:24 +08:00
JaguarJack
61b9a07d99 update:新增角色标识唯一性 2020-09-08 16:25:36 +08:00
JaguarJack
d75c455bdc update:更新用户部门搜索 2020-09-08 14:36:32 +08:00
JaguarJack
04e2b1ffe5 update:更新项目安装,增加项目domain配置 2020-09-08 14:34:03 +08:00
JaguarJack
14b5b3ce3a update:更新角色初始化数据 2020-09-08 14:31:30 +08:00
JaguarJack
a4e84ffa75 update:更新配置 2020-09-08 14:13:00 +08:00
JaguarJack
bd7f62b9ed add:新增导出用户 2020-09-08 14:12:42 +08:00
JaguarJack
3a2689db18 update:更新部分组件 2020-09-08 14:10:27 +08:00
JaguarJack
3fb55deaaf add:优雅的返回 Json 数据 2020-09-08 10:06:53 +08:00
JaguarJack
b07defb0e9 update 2020-09-07 20:14:03 +08:00
JaguarJack
377b72ae19 update 2020-09-07 19:57:58 +08:00
JaguarJack
dd023caf36 update:readme 2020-09-07 17:37:49 +08:00
JaguarJack
163d1c4bee update:更新部门及以下数据权限 2020-09-07 16:16:25 +08:00
JaguarJack
2c2b7f8723 fixed table 2020-09-07 14:05:36 +08:00
JaguarJack
d533aeaa9e update 2020-09-07 08:29:12 +08:00
JaguarJack
a6cebc3750 update:更新上传获取配置 2020-09-07 07:44:56 +08:00
JaguarJack
214ca68b44 update:wechat 管理 2020-09-06 16:42:29 +08:00
JaguarJack
e712f824f5 update:支持无限级的菜单隐藏 2020-09-06 11:18:12 +08:00
JaguarJack
f301f149fb update:更新获取方法 2020-09-06 10:58:13 +08:00
JaguarJack
96751d6974 update:导出数据 2020-09-05 17:18:31 +08:00
JaguarJack
da9aa45036 update:更新初始化数据 2020-09-05 17:13:50 +08:00
yanwenwu
9ec1285cb9 update:修复导出 2020-09-05 17:12:04 +08:00
JaguarJack
3947ba7386 update数据 2020-09-05 16:34:43 +08:00
JaguarJack
d0a9a41c68 更新到处数据 2020-09-05 16:33:34 +08:00
JaguarJack
7fbee46c73 update 初始化数据 2020-09-05 16:24:00 +08:00
JaguarJack
c8a7d0291c update 2020-09-05 16:01:18 +08:00
JaguarJack
d0044ee019 update 2020-09-04 20:29:38 +08:00
JaguarJack
3466c8ec1f code 更新 2020-09-04 19:28:47 +08:00
JaguarJack
b3be31750a upate 2020-09-04 19:28:30 +08:00
JaguarJack
ca7a3df823 update 2020-09-04 19:01:57 +08:00
JaguarJack
9a5e7010b1 update 2020-09-04 16:21:18 +08:00
JaguarJack
2e67214032 迁移数据 2020-09-04 10:45:18 +08:00
JaguarJack
c5fb6f9409 迁移 2020-09-04 10:09:26 +08:00
JaguarJack
8f73948223 开发者搜索 2020-09-03 19:07:19 +08:00
JaguarJack
2941eeac1e update 2020-09-03 18:55:25 +08:00
JaguarJack
e0007d4150 update:更新搜索 2020-09-02 20:46:30 +08:00
JaguarJack
0e3656c7cc update:更新表结构和模型字段 2020-09-02 11:20:10 +08:00
JaguarJack
44ed0b9788 update:调整部门管理 2020-09-01 07:58:36 +08:00
JaguarJack
1d660ba648 update:更新表结构 2020-08-30 11:31:25 +08:00
JaguarJack
202f7f1dea update:更新表结构 2020-08-30 11:23:10 +08:00
JaguarJack
b1f5c22c9d update:用户禁用 2020-08-20 21:02:16 +08:00
JaguarJack
a7609d9c77 update:修改部门权限标志 2020-08-18 19:32:33 +08:00
JaguarJack
cb9deeb7ce update:更新readme 2020-08-13 08:55:10 +08:00
JaguarJack
b62cf987d1 fixed:修改方法返回 2020-08-12 19:29:41 +08:00
JaguarJack
c6e235ca6c 更新readme 2020-08-11 21:24:18 +08:00
JaguarJack
03bb91cd9e update:优化数据表搜索 2020-08-10 11:37:34 +08:00
JaguarJack
e15838386f update:更新zip类 2020-08-10 11:17:32 +08:00
JaguarJack
bcf37924d3 update:更新解析parseClass 2020-08-10 11:16:42 +08:00
JaguarJack
1a965ff4f5 add:新增安装模块的类 2020-08-10 11:16:12 +08:00
JaguarJack
bbfb206210 update:更新打包工具 2020-08-10 11:15:48 +08:00
JaguarJack
2f76d0da38 update:更新上传模块 2020-08-10 11:15:12 +08:00
JaguarJack
ea6e45450c update:更新安装模块 2020-08-10 11:14:53 +08:00
JaguarJack
4bfa907191 update: 优化创建模块 2020-08-10 10:33:13 +08:00
JaguarJack
6c9f1cface Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2020-08-10 08:11:42 +08:00
JaguarJack
8776849d98 update:修改人物提示信息
:^O
2020-08-08 20:49:34 +08:00
JaguarJack
b5a589d4da update:新增进程最大内存限制 2020-08-08 20:43:58 +08:00
JaguarJack
c529d36f03 !2 1.修改描述,嘿嘿
Merge pull request !2 from sunhuan/master
2020-08-07 11:05:51 +08:00
sunhuan
de97a1319e 1.修改描述 2020-08-07 10:51:41 +08:00
JaguarJack
d410434979 fixed:菜单更新 2020-07-29 10:29:10 +08:00
JaguarJack
29732738dc add:新增菜单字段 2020-07-29 07:30:05 +08:00
JaguarJack
230ea26a1b update: 获取上传默认驱动 2020-07-29 07:29:42 +08:00
JaguarJack
d1a42637fe fixed:批量删除 2020-07-28 16:40:05 +08:00
JaguarJack
fae47bf246 update:优化代码 2020-07-28 08:19:51 +08:00
JaguarJack
cba66dfe58 fixed:migration 表前缀 2020-07-27 07:58:11 +08:00
JaguarJack
cc34e058f0 update:配置更新 2020-07-26 18:43:09 +08:00
JaguarJack
3ab7e207c9 update:修改attachments URL 路径地址 2020-07-26 08:28:54 +08:00
JaguarJack
e232062ba6 update:修改can方法 2020-07-25 21:33:20 +08:00
JaguarJack
3a0c537ce0 update:优化代码 2020-07-25 10:04:13 +08:00
JaguarJack
d9faa42905 新增issue模版 2020-07-25 08:46:01 +08:00
JaguarJack
99727f1c7d Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2020-07-25 08:34:24 +08:00
JaguarJack
7fc50c9916 Merge pull request #13 from qingmang/patch-1
后台增加权限判断
2020-07-25 07:50:13 +08:00
青芒科技
454fa43f8c Update Users.php 2020-07-24 22:16:34 +08:00
青芒科技
cdf6efde1d Update Users.php 2020-07-24 22:16:19 +08:00
JaguarJack
c65863d606 update:更新权限方法 2020-07-24 21:40:26 +08:00
青芒科技
c5650e80bd 后台增加权限判断
后台可以快捷的通过 `request()->user()->can('权限标识');` 来判断某个用户是否拥有某个权限,便于权限区分
2020-07-24 21:36:40 +08:00
JaguarJack
8d21dc8acc http客户端新增属性 2020-07-23 16:43:01 +08:00
JaguarJack
263c036e49 降低symfony/finder版本 2020-07-23 07:34:19 +08:00
JaguarJack
f0351246fc 新增zip&composer工具 2020-07-21 08:01:20 +08:00
JaguarJack
30f405f233 delete composer.lock 2020-07-21 07:57:58 +08:00
JaguarJack
94052b6e01 fixed bug 2020-07-20 17:03:49 +08:00
JaguarJack
ab9302e790 fixed:修复Finder not found 2020-07-20 17:01:01 +08:00
JaguarJack
f396732544 新增symfony/finder 2020-07-20 16:48:27 +08:00
JaguarJack
0fb344fcf3 update:修改微信粉丝同步 2020-07-19 16:55:38 +08:00
JaguarJack
78bb8bccd7 数据库备份 2020-07-19 16:47:58 +08:00
JaguarJack
027ba1acdb 优化catchConsole代码 2020-07-19 10:06:08 +08:00
JaguarJack
2757873ef2 新增文件操作 2020-07-19 09:15:15 +08:00
JaguarJack
6e1fdb2b74 优化模块下 commands 在cli模式下注入 2020-07-19 08:46:12 +08:00
JaguarJack
929f9b2a75 优化commands只有在Cli模式下注入 2020-07-19 08:40:49 +08:00
JaguarJack
db18e71906 Merge pull request #8 from tlerbao/master
登录日志新增数据搜索功能,修改路由Path单词用反了的问题
2020-07-18 20:51:11 +08:00
tlerbao
3f5b84ba45 操作日志和登录日志的路由Path单词用反了 2020-07-18 17:16:04 +08:00
tlerbao
bb1dd9b207 登录日志新增数据搜索功能 2020-07-18 17:12:07 +08:00
JaguarJack
eee53b3131 Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2020-07-16 14:35:19 +08:00
JaguarJack
a86387a47e fixed:修复表信息获取 2020-07-16 14:12:44 +08:00
JaguarJack
b538c08b88 Merge pull request #6 from tlerbao/master
操作日志新增批量删除
2020-07-15 14:57:59 +08:00
JaguarJack
ce38bc741b Merge pull request #5 from qingmang/patch-2
设置departments获取的默认值
2020-07-15 14:55:23 +08:00
tlerbao
142fd71b56 操作日志新增条件查询,并简单优化了操作日志控制器 2020-07-15 11:39:55 +08:00
tlerbao
a6ad9b63dd 操作日志新增批量删除 2020-07-14 21:06:10 +08:00
JaguarJack
8a901e89cb 删除冗余代码&修复bug 2020-07-14 17:35:16 +08:00
JaguarJack
fc93826016 修改auth认证 2020-07-14 12:21:29 +08:00
青芒科技
98b2d7d31b 设置departments获取的默认值
只有自定义数据才存在departments
2020-07-13 19:00:53 +08:00
JaguarJack
33bdd01933 移除不必要的包 2020-07-13 17:57:57 +08:00
JaguarJack
32b87baeee 优化 Request 认证 2020-07-13 17:07:18 +08:00
JaguarJack
19c092dffc 删除冗余代码 2020-07-13 17:06:54 +08:00
JaguarJack
81e7f78419 新增模块上传 2020-07-13 17:06:21 +08:00
JaguarJack
a5416bd0ad 修复生成代码 2020-07-13 17:05:34 +08:00
JaguarJack
6d51b5bc76 新增开发者认证配置 2020-07-13 17:04:53 +08:00
JaguarJack
04e008fcfa 开发者认证 2020-07-13 17:04:35 +08:00
JaguarJack
7ef4efa37a 新增开发者 2020-07-13 15:28:38 +08:00
JaguarJack
1644076abe Guard 未设置抛出异常 2020-07-13 09:04:57 +08:00
JaguarJack
5b43786432 插件上传 2020-07-12 18:03:48 +08:00
JaguarJack
1e8b5510f1 修复远程下载模块 2020-07-11 21:44:39 +08:00
JaguarJack
7adfc93190 新增安装模块命令 2020-07-11 16:13:06 +08:00
JaguarJack
b9c156e5a7 修改打包命令 2020-07-11 16:12:17 +08:00
JaguarJack
bcdf6cd9c7 修改catchadmin根目录 2020-07-11 15:52:30 +08:00
root
e17846571c 新增下载保存地址方法 2020-07-11 15:02:05 +08:00
JaguarJack
359381fec6 生成代码新增回滚功能 2020-07-11 10:59:57 +08:00
root
42e75f50ff 修改日志记录方式 2020-07-11 10:10:42 +08:00
JaguarJack
454e1fcd55 去除不必要的包 2020-07-10 16:38:42 +08:00
JaguarJack
5584fa66da 修复定时任务秒级执行 2020-07-10 08:49:31 +08:00
JaguarJack
87ec38d1dd 新增调度中心 2020-07-10 08:35:14 +08:00
JaguarJack
6db13b9eab 修改信号处理 2020-07-09 22:01:52 +08:00
JaguarJack
e678b4ce51 新增调度配置 2020-07-09 21:56:39 +08:00
JaguarJack
b8de40a60f 新增守护控制选项 2020-07-09 21:56:17 +08:00
JaguarJack
c84d5a2a17 修复创建最大进程数目之后可继续创建 2020-07-09 21:17:34 +08:00
JaguarJack
9335556197 worker状态切换到table内存操作 2020-07-09 21:03:16 +08:00
JaguarJack
40ed25816c 新增 swoole table 2020-07-09 21:02:44 +08:00
JaguarJack
2a593b179a 异常日志记录 2020-07-09 15:41:53 +08:00
JaguarJack
a5b6b479ce 增加USR1信号,实时获取 worker 信息 2020-07-09 10:04:31 +08:00
JaguarJack
104ad3f744 修复worker等待状态bug 2020-07-09 08:37:03 +08:00
JaguarJack
ea32a4cd33 worker状态管理 2020-07-09 08:28:29 +08:00
JaguarJack
a3f378eca8 写入 worker 状态信息 2020-07-08 19:47:35 +08:00
JaguarJack
bcc4237140 修复定时任务无法准时启动 2020-07-08 17:48:45 +08:00
JaguarJack
4fec98f939 新增 crontab 组件 2020-07-07 16:58:34 +08:00
JaguarJack
f15eedfa9c 新增调度命令 2020-07-07 16:58:16 +08:00
JaguarJack
da683a3592 Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2020-07-06 08:54:33 +08:00
JaguarJack
7adfb6a0ae Merge pull request #4 from qingmang/patch-1
fix:自定义数据范围更新追加部门数据更新
2020-07-06 08:54:11 +08:00
青芒科技
a73883cc79 fix:自定义数据范围更新追加部门数据更新 2020-07-05 20:15:40 +08:00
JaguarJack
3235e98c38 新增版本信息 2020-07-05 16:36:28 +08:00
JaguarJack
bb38e3bdac 修复更新权限父类未更新子类模块 2020-07-05 07:20:01 +08:00
JaguarJack
9092b64c1f 新增超级管理员判断&权限范围 2020-07-04 21:56:47 +08:00
JaguarJack
e798098a05 修改数据范围 2020-07-04 21:35:01 +08:00
JaguarJack
c2da2e5806 修复数据权限 bug 2020-07-04 14:28:59 +08:00
JaguarJack
6e1be051e2 修改模版 2020-07-04 11:32:04 +08:00
JaguarJack
a34d687203 新增request post方法加入 creator_id 2020-07-04 10:44:39 +08:00
JaguarJack
2746d565e4 修复添加部门没有存入creator_id 2020-07-04 10:43:09 +08:00
JaguarJack
fda520bad3 修改modulejson信息 2020-07-03 21:24:42 +08:00
JaguarJack
1abcc5045f 新增令牌桶限流 2020-07-02 18:41:47 +08:00
JaguarJack
5e076a6eb7 新增滑动窗口限流 2020-07-02 17:28:01 +08:00
JaguarJack
349f36df21 降低phpunit版本 2020-07-02 14:30:25 +08:00
JaguarJack
9ec043ba34 catchConsole加入容器,提高性能 2020-07-02 14:22:02 +08:00
JaguarJack
e51cbc6850 修改wechat commands 注入方式 2020-07-02 14:01:47 +08:00
JaguarJack
26e26b60a7 新增 console 统一注入 2020-07-02 14:01:05 +08:00
JaguarJack
e35b14a883 新增文件处理 2020-07-02 13:19:23 +08:00
JaguarJack
24e1506743 修改启用/禁用模块删除对应的菜单 2020-07-01 15:47:06 +08:00
JaguarJack
51672734a6 优化sql生成&添加creator_id 2020-07-01 15:24:42 +08:00
JaguarJack
1a20159776 新增redis固定窗口限流 2020-06-30 18:06:01 +08:00
JaguarJack
bd840134ad 修改异常信息 2020-06-30 17:42:07 +08:00
JaguarJack
9740df6a97 修改路由生成 2020-06-30 10:46:39 +08:00
JaguarJack
0ef84fea08 修改模型模版 2020-06-30 10:31:27 +08:00
JaguarJack
2b4f9823ff 优化代码生成 2020-06-30 10:14:27 +08:00
JaguarJack
051627547e 优化微信图文 2020-06-30 08:40:00 +08:00
JaguarJack
16a19312a9 回复搜索 2020-06-30 07:36:38 +08:00
JaguarJack
7dedec17d9 修复回复media_id 2020-06-30 07:17:55 +08:00
JaguarJack
b9f055e052 新增上传文件类型 2020-06-30 07:17:13 +08:00
JaguarJack
57d26f8003 完善回复功能 2020-06-29 22:04:40 +08:00
JaguarJack
655541210a 新增禁用/启用 2020-06-29 22:01:47 +08:00
JaguarJack
f2affda157 新增上传 2020-06-29 20:02:33 +08:00
JaguarJack
08fb8b3397 微信回复功能 2020-06-29 19:51:44 +08:00
JaguarJack
09c409fc76 修改权限数据 2020-06-28 15:09:42 +08:00
JaguarJack
6841f6c385 新增系统权限数据 2020-06-28 15:09:15 +08:00
JaguarJack
99136f33d1 修改微信权限数据 2020-06-28 15:08:56 +08:00
JaguarJack
41eb836634 优化提示 2020-06-28 11:32:50 +08:00
JaguarJack
db9428961f 微信权限菜单 2020-06-28 08:45:14 +08:00
JaguarJack
cc5805f410 修改上传 2020-06-28 08:34:19 +08:00
JaguarJack
1c9e98ff2a 新增微信图文 2020-06-28 08:33:49 +08:00
JaguarJack
7152661210 修改本地存储路径 2020-06-28 08:33:34 +08:00
JaguarJack
59774e7958 新增微信认证url 2020-06-26 22:08:27 +08:00
JaguarJack
bcd7215333 新增事件消息 2020-06-26 22:08:01 +08:00
JaguarJack
a232f555c3 微信菜单 2020-06-26 16:27:20 +08:00
JaguarJack
ce71b10d1c 修改数据库基础操作 2020-06-25 09:25:34 +08:00
JaguarJack
707070a06e 修改创建模块命令 2020-06-25 09:25:02 +08:00
JaguarJack
fca8980715 新增角色初始化数据 2020-06-25 08:36:59 +08:00
JaguarJack
4dc2978d61 新增模块权限导出 2020-06-25 08:36:29 +08:00
JaguarJack
cfaec3fbc3 新增seedPath创建方法 2020-06-25 08:35:52 +08:00
JaguarJack
d2bc7a25c0 优化Catchadmin服务 2020-06-24 10:07:53 +08:00
JaguarJack
5f5260a639 优化开启/关闭模块 2020-06-24 10:07:11 +08:00
JaguarJack
f6783cb13e 优化服务发现 2020-06-24 09:46:21 +08:00
JaguarJack
ee04005d69 架构调整,服务调整 2020-06-24 09:11:48 +08:00
JaguarJack
9125292aa8 新增模块抽象服务 2020-06-24 09:11:30 +08:00
JaguarJack
2c18af0aa7 架构调整路由加载 2020-06-24 09:11:08 +08:00
JaguarJack
2d95212973 调整架构,新增微信模块服务 2020-06-24 09:10:24 +08:00
JaguarJack
0e7453a6fe 调整架构,新增系统模块服务 2020-06-24 09:10:01 +08:00
JaguarJack
8c32893c91 调整架构,新增权限模块服务 2020-06-24 09:09:37 +08:00
JaguarJack
805b04a7f8 新增事件监听 2020-06-24 09:09:10 +08:00
JaguarJack
8dfd4596be 删除配置 2020-06-24 09:08:06 +08:00
JaguarJack
8b4404df55 login新增Service 2020-06-24 08:47:46 +08:00
JaguarJack
23fa6ab097 新增禁止开启模块 2020-06-23 21:37:37 +08:00
JaguarJack
f18766c20a 优化范围查询 2020-06-22 15:19:50 +08:00
JaguarJack
d873ba10f9 修复模块服务发现导致的兼容问题 2020-06-22 12:36:25 +08:00
JaguarJack
51d237d0f0 安装新增模块服务发现 2020-06-22 08:05:51 +08:00
JaguarJack
6e76c173a7 优化catchQuery 2020-06-22 07:55:39 +08:00
JaguarJack
a3dd8282b3 完善微信粉丝和标签 2020-06-22 07:55:16 +08:00
JaguarJack
317a9ef595 优化角色权限分配 2020-06-21 21:07:15 +08:00
JaguarJack
e6d7ee8f55 修改命令 2020-06-21 18:04:55 +08:00
JaguarJack
fbf9c11191 微信标签管理 2020-06-21 18:04:30 +08:00
JaguarJack
4392f25e97 优化微信错误码 2020-06-21 16:20:02 +08:00
JaguarJack
73c7788218 新增微信错误码 2020-06-21 14:42:02 +08:00
JaguarJack
835b93eaaf 优化微信服务 2020-06-21 14:41:46 +08:00
JaguarJack
092567a169 新增微信用户 2020-06-21 14:41:22 +08:00
JaguarJack
028333fae3 新增基类仓库 2020-06-21 13:24:15 +08:00
JaguarJack
7b0aa49c21 新增微信响应错误 2020-06-21 13:23:43 +08:00
JaguarJack
c624dc1777 新增微信公众号错误 2020-06-21 13:23:22 +08:00
JaguarJack
dc08715bc7 新增命令行进度条 2020-06-21 10:50:29 +08:00
JaguarJack
11f6419b4f 抽象scope trait 2020-06-21 10:50:05 +08:00
JaguarJack
448154f363 微信用户列表 2020-06-21 10:48:55 +08:00
JaguarJack
cd8ff84f02 微信用户同步 2020-06-21 10:48:11 +08:00
JaguarJack
97724b04df 新增catchadmin模块发现 2020-06-20 16:57:37 +08:00
JaguarJack
6e9c0aed32 删除输出 2020-06-20 09:29:45 +08:00
JaguarJack
de6470fd0e 优化模块服务发现 2020-06-20 09:13:11 +08:00
JaguarJack
bd21242410 删除登陆模块service 2020-06-20 09:12:19 +08:00
JaguarJack
f21716d5a6 修复获取模块信息bug 2020-06-20 08:51:28 +08:00
JaguarJack
49500956dd 删除冗余代码 2020-06-20 08:51:11 +08:00
JaguarJack
9ff6c8d883 新增模块服务安装命令 2020-06-20 08:50:49 +08:00
JaguarJack
6612dfd8b7 优化安装 2020-06-20 08:50:21 +08:00
JaguarJack
93c1c11853 新增模块json信息 2020-06-20 08:49:44 +08:00
JaguarJack
49a8d04157 新增微信服务 2020-06-20 08:49:16 +08:00
JaguarJack
1d1afe468c 新增微信用户同步表 2020-06-19 20:58:11 +08:00
JaguarJack
20b3fd477f 新增用户管理 2020-06-19 19:29:21 +08:00
JaguarJack
e4273e5a1a 新增微信动态调用 2020-06-19 19:28:56 +08:00
JaguarJack
2c9e22ac6c 新增敏感词库菜单 2020-06-18 17:45:45 +08:00
JaguarJack
e717f56416 优化导出命令 2020-06-18 17:45:04 +08:00
JaguarJack
96f04545db 新增trie tree缓存命令 2020-06-18 17:08:47 +08:00
JaguarJack
cbfcce919f 新增敏感词请求验证 2020-06-18 16:30:25 +08:00
JaguarJack
1f3c025f36 新增敏感词验证 2020-06-18 16:29:54 +08:00
JaguarJack
b4b0d624a6 fixed dfa bug 2020-06-18 16:29:26 +08:00
JaguarJack
5a198f8f0b 新增phpunit 2020-06-18 10:50:38 +08:00
JaguarJack
fcc6fd035d 新增redis配置 2020-06-17 23:03:04 +08:00
JaguarJack
4fc4577be3 新增DFA算法过滤敏感词 2020-06-17 23:02:52 +08:00
JaguarJack
dec79f2b28 新增敏感词缓存key 2020-06-17 23:02:12 +08:00
JaguarJack
f14107dc44 新增敏感词搜索 2020-06-17 16:19:51 +08:00
JaguarJack
727640396e 新增子查询方法 addSelectSub 2020-06-17 16:19:21 +08:00
JaguarJack
e105492d27 修改排序 2020-06-17 14:40:01 +08:00
JaguarJack
c450c4afc5 新增敏感词库 2020-06-17 14:29:31 +08:00
JaguarJack
13d3734dba 修改排序 2020-06-17 13:24:02 +08:00
JaguarJack
6977442b05 去除重写Order 方法,新增 CatchOrder 2020-06-17 13:23:43 +08:00
JaguarJack
3b063ac1fd fixed conflict 2020-06-08 08:56:05 +08:00
JaguarJack
5609d4fd09 fixed 2020-06-08 08:54:50 +08:00
JaguarJack
66acbeee8b 优化微信发布命令 2020-06-07 14:23:26 +08:00
JaguarJack
5231770bab 新增微信扩展 2020-06-07 14:23:07 +08:00
JaguarJack
ec5a5a8402 新增微信模块 2020-06-07 14:22:41 +08:00
JaguarJack
e9c8940730 新增微信发布 2020-06-06 22:37:36 +08:00
JaguarJack
333d0be409 修改readme 2020-06-06 21:50:36 +08:00
JaguarJack
ffeec69333 数据范围查询 2020-06-06 18:57:58 +08:00
JaguarJack
ac56a7b80d 添加必要注释 2020-06-06 09:21:24 +08:00
JaguarJack
9a07ae1e1b 修改readme 2020-06-06 08:58:55 +08:00
JaguarJack
08b7a1b17c 修改parseclass 2020-06-05 16:20:50 +08:00
JaguarJack
d232ebb207 优化 2020-06-05 15:58:16 +08:00
JaguarJack
8550c99133 新增parseclass组件 2020-06-05 15:35:51 +08:00
JaguarJack
f55ff91554 修改方法获取 2020-06-05 15:35:31 +08:00
JaguarJack
f9ed43017f 新增权限方法获取 2020-06-05 15:20:22 +08:00
JaguarJack
c06e7b8694 更新附件模型 2020-06-01 21:28:04 +08:00
JaguarJack
fe6ea82014 新增附件事件 2020-06-01 21:25:46 +08:00
JaguarJack
39c0ec4c48 删除冗余代码 2020-05-28 08:24:49 +08:00
JaguarJack
107a7d48da 优化模型生成命令 2020-05-28 06:38:10 +08:00
JaguarJack
b57d7f95c3 优化模型代码生成 2020-05-28 06:37:32 +08:00
JaguarJack
5face1c077 优化excel导出 2020-05-26 22:55:02 +08:00
JaguarJack
a5a05b1e88 增加内存设置选项 2020-05-26 22:44:48 +08:00
JaguarJack
ea6a4b15a8 修改搜索 2020-05-26 22:39:06 +08:00
JaguarJack
c60d8d2dc9 优化搜索 2020-05-26 09:32:52 +08:00
JaguarJack
bae43ad382 优化excel导出 2020-05-25 22:50:51 +08:00
JaguarJack
74a42e7022 修改设置开始列无效bug 2020-05-25 22:39:00 +08:00
JaguarJack
c04530a1be 优化 excel 2020-05-25 19:55:25 +08:00
JaguarJack
2074c1f65d 新增 excel 工具 2020-05-25 19:47:54 +08:00
JaguarJack
c0e3726775 修改README 2020-05-25 15:07:01 +08:00
JaguarJack
0f59685ae3 修服左侧菜单排序不生效 bug 2020-05-25 14:30:28 +08:00
JaguarJack
dfcec7394f 修改readme 2020-05-24 10:56:08 +08:00
JaguarJack
8bf7380d82 优化 auth 单例获取用户,支持 guard 获取 2020-05-23 14:04:23 +08:00
JaguarJack
fa04341608 优化 auth 单例获取用户,防止多次查询 2020-05-23 11:10:28 +08:00
JaguarJack
167ea743a0 优化 http 客户端 2020-05-22 18:24:10 +08:00
JaguarJack
30e7829d21 优化 2020-05-22 15:56:28 +08:00
JaguarJack
1d1eaa0338 优化打包类 2020-05-22 15:45:33 +08:00
JaguarJack
a60880d327 优化 http 客户端 2020-05-22 15:45:14 +08:00
JaguarJack
19c62e049c 修复异常错误显示 2020-05-22 15:22:21 +08:00
JaguarJack
0df821d1a4 优化用户立标 2020-05-22 15:21:05 +08:00
JaguarJack
00a37a05f2 优化command 2020-05-22 14:09:59 +08:00
JaguarJack
93f22ab338 修改方法为静态 2020-05-22 14:09:48 +08:00
JaguarJack
ca5e76497c 完善 http 客户端 2020-05-22 14:08:53 +08:00
JaguarJack
b7d951bdb7 新增facade方法注释,以便用户访问 2020-05-22 14:08:35 +08:00
JaguarJack
bfc576b437 新增前缀获取 2020-05-22 14:07:55 +08:00
JaguarJack
5ac51366f2 新增http客户端 2020-05-21 23:08:16 +08:00
yanwenwu
853ebe7437 优化配置 2020-05-20 19:21:28 +08:00
yanwenwu
c635a322bb 修改配置获取类型错误导致前端报错 2020-05-20 12:52:25 +08:00
yanwenwu
70b6b0407c 菜单新增隐藏显示功能 2020-05-20 11:31:04 +08:00
yanwenwu
ff1d7dfd2e 修复代码生成器bug 2020-05-20 11:03:21 +08:00
yanwenwu
181ceefd55 修复migraions地址 2020-05-20 10:06:42 +08:00
yanwenwu
48f572168f 修复未定义table 2020-05-19 11:03:42 +08:00
yanwenwu
64ce1243b4 fixed bug 2020-05-19 08:22:48 +08:00
yanwenwu
9da4072b30 新增字段 2020-05-18 15:47:32 +08:00
yanwenwu
52e25103d0 新增状态码 2020-05-18 13:42:26 +08:00
yanwenwu
2361be7d71 修改过期token返回码 2020-05-18 13:42:08 +08:00
yanwenwu
5057f3eb9e refresh token 2020-05-18 13:41:46 +08:00
yanwenwu
b4bb0a1910 logout 2020-05-18 10:12:33 +08:00
yanwenwu
f913f76bd2 修改readme 2020-05-17 22:41:14 +08:00
yanwenwu
45383c2230 修改readme 2020-05-17 17:09:53 +08:00
JaguarJack
dbc6eb2b48 修改菜单 2020-05-17 16:08:40 +08:00
JaguarJack
3f814116de 修改安装命令 2020-05-17 15:49:42 +08:00
JaguarJack
db2aba9b1a update readme 2020-05-16 23:44:22 +08:00
JaguarJack
68cdec973a update README.md. 2020-05-16 21:26:39 +08:00
JaguarJack
82a99d7d17 修改readme 2020-05-16 21:09:05 +08:00
JaguarJack
a90f289792 修改READ 2020-05-16 21:06:50 +08:00
JaguarJack
9b2c4aa905 新增添加菜单命令 2020-05-08 20:56:21 +08:00
JaguarJack
d68891035b fixed 生成表 2020-05-08 19:21:31 +08:00
JaguarJack
6f8552fa70 fixed bug 2020-05-07 13:45:31 +08:00
JaguarJack
278b078937 修复创建人ID无法获取 2020-05-06 22:16:55 +08:00
JaguarJack
0cc8dc7927 增加扩展 2020-05-06 17:55:16 +08:00
JaguarJack
9dda665ddc 新增工具方法 2020-05-06 17:41:36 +08:00
JaguarJack
056abcd9f1 新增操作中间件 2020-05-06 17:41:09 +08:00
JaguarJack
98c99e05f3 分离日志操作权限 2020-05-06 17:40:51 +08:00
JaguarJack
339f441d4f 优化角色权限 2020-05-06 11:46:40 +08:00
JaguarJack
72eb174946 优化代码生成 2020-05-05 21:52:44 +08:00
JaguarJack
635f3e00d0 修改SQL生成 2020-05-05 12:35:36 +08:00
JaguarJack
9e5bbeae5a 修改模版 2020-05-05 12:34:32 +08:00
JaguarJack
0bc448f8e8 readme 2020-05-02 06:39:18 +08:00
JaguarJack
dd1ce48646 fixed bug 2020-05-01 01:00:55 +08:00
JaguarJack
ae01ba64b2 fixed bug 2020-05-01 00:59:46 +08:00
JaguarJack
892f8f2aad fixed bug 2020-05-01 00:38:41 +08:00
JaguarJack
4e38e7ede2 fiexed bug 2020-04-30 18:15:48 +08:00
JaguarJack
fbc4a6201a 增加注释 2020-04-30 18:15:34 +08:00
JaguarJack
5fb45c0d49 修改操作日志参数长度 2020-04-30 18:10:38 +08:00
JaguarJack
2febc2bb56 修改部门排序 2020-04-30 17:58:55 +08:00
JaguarJack
e1abef2319 新增order 2020-04-30 17:58:36 +08:00
JaguarJack
dd0ad744e6 优化打包命令 2020-04-30 15:24:16 +08:00
JaguarJack
b86347a993 优化 2020-04-30 15:24:02 +08:00
JaguarJack
196dfbcbda 新增http客户端 2020-04-30 15:23:36 +08:00
JaguarJack
cfc7d8a48c 新增包的更新和打包 2020-04-30 14:52:01 +08:00
JaguarJack
06ee75d496 修改打包命令 2020-04-30 14:51:32 +08:00
JaguarJack
b192a0151f recover 2020-04-29 17:37:45 +08:00
JaguarJack
4d444e9bbc 新增解析功能 2020-04-29 17:35:29 +08:00
JaguarJack
45af3fbc5f fixed install biug 2020-04-29 16:03:24 +08:00
JaguarJack
4a5e4353be 新增扩展 2020-04-29 15:54:30 +08:00
JaguarJack
ab3e420085 delete 2020-04-29 15:30:49 +08:00
JaguarJack
a437d2ed40 fixed bug 2020-04-29 15:25:41 +08:00
JaguarJack
d8ad1f6b87 修改数据初始化 2020-04-29 15:06:38 +08:00
JaguarJack
610f48b4ec 新增tools 2020-04-29 15:06:13 +08:00
JaguarJack
514bb6b520 新增导入树状数据方法 2020-04-29 15:05:49 +08:00
JaguarJack
76855d6b5d 生成控制器 2020-04-29 11:42:48 +08:00
JaguarJack
b30e57bf01 优化代码生成 2020-04-29 11:41:54 +08:00
JaguarJack
f8fb57c9c6 移除方法 2020-04-29 09:02:43 +08:00
JaguarJack
64c03bdfd3 优化代码生成 2020-04-29 09:02:20 +08:00
JaguarJack
7f72784bfb 修改用户 2020-04-28 22:04:01 +08:00
JaguarJack
08aee72ab9 修改日志列表 2020-04-28 22:02:50 +08:00
JaguarJack
50bcb7e289 新增列表查询 2020-04-28 22:02:23 +08:00
JaguarJack
0b546a20be 代码生成器 2020-04-28 22:02:03 +08:00
JaguarJack
d044ac6d8a 新增模型 2020-04-28 16:34:55 +08:00
JaguarJack
011c138439 修改操作事件 2020-04-28 16:34:31 +08:00
JaguarJack
435e1b6399 修改登陆事件 2020-04-28 16:34:17 +08:00
JaguarJack
760ad2a51b readme 2020-04-26 11:06:48 +08:00
JaguarJack
5fa78eda58 修改Query 2020-04-24 14:31:46 +08:00
JaguarJack
3f888f909a fixed migrate create failed 2020-04-23 19:47:00 +08:00
JaguarJack
fbbfc70d39 修改 2020-04-23 14:09:27 +08:00
JaguarJack
9e56f9f85e 优化权限keepalive字端 2020-04-23 14:04:26 +08:00
JaguarJack
e7295fa767 fixed bug 2020-04-22 22:47:31 +08:00
JaguarJack
b3682b1ee6 修改初始化数据 2020-04-22 22:16:41 +08:00
JaguarJack
498b45059b 修改数据 2020-04-22 22:10:47 +08:00
JaguarJack
306c36df85 优化角色 2020-04-22 21:29:13 +08:00
JaguarJack
b71bba6a1e 新增基础操作 2020-04-22 20:17:39 +08:00
JaguarJack
e7491555e8 修改权限 2020-04-22 20:17:19 +08:00
JaguarJack
ef64b8a8cb 权限表新增 level 字段 2020-04-22 20:16:48 +08:00
JaguarJack
05abc92ad9 修改配置 2020-04-22 07:08:07 +08:00
JaguarJack
90241e9a8f 优化auth 2020-04-22 07:02:40 +08:00
JaguarJack
3469cc2adf 优化代码 2020-04-22 07:00:38 +08:00
JaguarJack
6ac556e819 修改权限 2020-04-22 06:43:26 +08:00
JaguarJack
0fd9d3dcb4 修改数据 2020-04-22 06:38:12 +08:00
JaguarJack
aa56154a28 修改用户路由 2020-04-22 06:08:40 +08:00
JaguarJack
57abdd4fd9 删除冗余代码 2020-04-22 06:07:53 +08:00
JaguarJack
6b227688e4 优化登陆 2020-04-22 06:07:14 +08:00
JaguarJack
308ee3120e 迁移用户模块 2020-04-22 06:06:57 +08:00
JaguarJack
fd9ce382db 更改依赖 2020-04-22 05:54:15 +08:00
JaguarJack
67b810b06f delete user module 2020-04-22 05:53:38 +08:00
JaguarJack
86dfe36714 修改数据 2020-04-21 22:22:27 +08:00
JaguarJack
6ac0e3ebf2 修复权限不全bug 2020-04-21 22:19:10 +08:00
JaguarJack
33fee182d2 优化安装 2020-04-21 21:36:25 +08:00
JaguarJack
20410ba52c 修改错误数据 2020-04-21 21:23:58 +08:00
JaguarJack
49f948fdd1 新增createdBy方法 2020-04-21 21:16:23 +08:00
JaguarJack
3d65d111ee fixed bug 2020-04-21 21:16:04 +08:00
JaguarJack
129582a446 部门数据 2020-04-21 21:09:09 +08:00
JaguarJack
8084e11805 新增seed 2020-04-21 21:06:53 +08:00
JaguarJack
dd46a28096 新增数据 2020-04-21 19:56:44 +08:00
JaguarJack
9b2ac5fd49 修改配置 2020-04-21 19:45:58 +08:00
JaguarJack
4f9cf56e69 修改初始化数据 2020-04-21 19:38:27 +08:00
JaguarJack
5e59f507af fixed bug 2020-04-21 19:34:03 +08:00
JaguarJack
9594ea0fc4 修改操作日志 2020-04-21 19:26:35 +08:00
JaguarJack
2f77658f41 修改权限中间件 2020-04-21 19:24:16 +08:00
JaguarJack
6cd67c6498 权限更新 2020-04-21 19:22:11 +08:00
JaguarJack
cfe2a005c0 fixed bug 2020-04-21 19:18:32 +08:00
JaguarJack
7131a6c878 合并配置 2020-04-21 17:07:19 +08:00
JaguarJack
010cc10d53 配置管理优化 2020-04-21 14:07:06 +08:00
JaguarJack
e82e058550 修复循环插入数据导致数据错乱 2020-04-21 10:51:25 +08:00
JaguarJack
1b954c1b16 新增配置管理 2020-04-21 10:34:50 +08:00
JaguarJack
be743d9d23 优化模型生成命令 2020-04-17 17:10:39 +08:00
JaguarJack
2c350cbceb fixed bug 2020-04-17 16:36:24 +08:00
JaguarJack
20091aaf43 日志动态分页数量 2020-04-17 15:02:50 +08:00
JaguarJack
a5c193f192 防止中文转义 2020-04-17 14:30:49 +08:00
JaguarJack
f777816e18 修复命名不规范 2020-04-17 06:48:14 +08:00
JaguarJack
f1f3df2bc8 重写路由 2020-04-17 06:47:19 +08:00
JaguarJack
c4d29b5cbf 重写事件 2020-04-17 06:47:04 +08:00
JaguarJack
1b8f0df628 修改权限 2020-04-16 17:14:56 +08:00
JaguarJack
def5e396e1 新增搜索 2020-04-16 17:14:37 +08:00
JaguarJack
6da68f09cd 修改权限返回数据结构 2020-04-14 20:31:38 +08:00
JaguarJack
9ddc932e89 修改模型生成 2020-04-14 19:17:13 +08:00
JaguarJack
b47ff98bb6 新增权限模型 2020-04-14 19:16:28 +08:00
JaguarJack
48298273dd 禁止项目安装时候cache router 2020-04-13 19:25:32 +08:00
JaguarJack
9548cb34fd permission修改文件 2020-04-13 15:36:22 +08:00
吴彦文
56f6ba90a6 优化install 2020-04-08 17:44:35 +08:00
吴彦文
8d10baa35f 修复重复env导致安装失败 2020-04-06 19:18:31 +08:00
吴彦文
e61f3a4115 异常退出删除.env 2020-04-06 18:29:14 +08:00
wuyanwen
4271a70b16 fixed bug 2020-03-11 14:14:27 +08:00
wuyanwen
49a4e56f48 delete 2020-03-10 16:51:05 +08:00
wuyanwen
29482f4e31 优化 2020-03-10 16:50:04 +08:00
wuyanwen
a90fd31b87 delete 2020-03-07 12:20:55 +08:00
wuyanwen
35a9ecbc82 修改ipv6长度 2020-03-06 17:06:44 +08:00
wuyanwen
defd10ab91 修改服务 2020-02-26 11:47:27 +08:00
wuyanwen
f812033ccc 修改readme 2020-02-26 09:06:35 +08:00
wuyanwen
4c48d0c71d Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2020-02-24 10:58:29 +08:00
wuyanwen
52e166b330 修改 2020-02-24 10:58:08 +08:00
jaguarjack
91d4f4a54d fixed conflict 2020-02-21 22:34:33 +08:00
jaguarjack
6b7146486c 修改 2020-02-21 22:32:50 +08:00
wuyanwen
3a58e928b6 修改install 2020-02-21 08:09:33 +08:00
wuyanwen
b998d58dea 删除冗余路由 2020-02-20 18:09:30 +08:00
wuyanwen
ff1aecce37 修改readme 2020-02-20 15:45:29 +08:00
wuyanwen
4e1a2d07d6 修改composer 2020-02-20 15:45:21 +08:00
wuyanwen
b0ee2e84d2 删除form 2020-02-20 13:46:06 +08:00
wuyanwen
42059247b2 新增事件配置 2020-02-20 13:45:13 +08:00
wuyanwen
6c5383f83c 益处service 2020-02-20 13:44:54 +08:00
wuyanwen
bcb671697c 切换service 2020-02-20 13:44:25 +08:00
wuyanwen
a9aa28bd77 修复win环境下apache头信息丢失 2020-02-18 17:27:24 +08:00
wuyanwen
bf98751ed5 切换路由中间件可配置 2020-02-18 14:52:32 +08:00
wuyanwen
ebe5f5757a 切换中间件,防止串应用 2020-02-18 14:44:16 +08:00
wuyanwen
fd1798875f 修改配置 2020-02-15 18:05:25 +08:00
wuyanwen
c4bdcd4152 新增wechat 2020-02-15 18:05:13 +08:00
wuyanwen
98f2e4bc31 修改异常错误信息 2020-02-13 19:55:01 +08:00
wuyanwen
0952e8f6f8 修改readme 2020-02-13 16:35:42 +08:00
wuyanwen
13d5b1a7fc 修改数据错误 2020-02-13 14:34:56 +08:00
wuyanwen
2c00ae5bdd 修改 apache 重写规则 2020-02-13 12:30:18 +08:00
wuyanwen
f562a3e8bc 修改readme 2020-02-13 11:55:58 +08:00
yanwenwu
81abf41e31 修改用户名 2020-02-10 13:04:27 +08:00
yanwenwu
db9a9327e5 修改登录 2020-02-08 18:30:56 +08:00
yanwenwu
1377a3a589 支持编辑器跳转 2020-02-06 12:02:38 +08:00
yanwenwu
4b0e9f24b9 删除package 2020-02-03 14:22:55 +08:00
yanwenwu
766d156bf8 新增附件管理 2020-02-02 22:11:38 +08:00
yanwenwu
a752c7914a 重置 2020-02-02 22:11:12 +08:00
yanwenwu
ae37218fcd 重新绑定异常处理 2020-02-02 22:10:52 +08:00
yanwenwu
6040ee4873 新增异常处理 2020-02-02 22:10:30 +08:00
yanwenwu
0c0238f664 修改上传 2020-02-02 22:10:14 +08:00
yanwenwu
fad98021e4 修改工具类 2020-02-02 22:09:53 +08:00
yanwenwu
e5ebc34d84 修改readme 2020-02-02 18:11:27 +08:00
yanwenwu
50410d640a 新增上传设置 2020-02-01 16:55:07 +08:00
yanwenwu
d0687df4de 修改服务 2020-02-01 15:42:13 +08:00
wuyanwen
b18390739f 修改request 2020-01-25 22:23:21 +08:00
wuyanwen
9c1eb59961 新增工具方法 2020-01-25 22:23:10 +08:00
wuyanwen
04b491621e 修改上传 2020-01-25 22:22:56 +08:00
wuyanwen
7dd40dc4aa 修改配置 2020-01-25 22:22:42 +08:00
wuyanwen
a8c98a0a05 新增附件管理 2020-01-25 22:22:29 +08:00
wuyanwen
5181915e3c 新增上传 2020-01-25 22:22:13 +08:00
wuyanwen
021041218b 修改权限 2020-01-25 20:33:04 +08:00
wuyanwen
88971b672d 修改权限 2020-01-25 20:32:31 +08:00
yanwenwu
09f8ef88ea 修改配置 2020-01-25 20:16:28 +08:00
wuyanwen
3e7106f9aa 修改 2020-01-25 20:08:53 +08:00
yanwenwu
10687ea93c 增加composer插件 2020-01-25 20:07:08 +08:00
yanwenwu
714837c8df 新增cloud配置 2020-01-25 20:06:36 +08:00
yanwenwu
b9acfbea2b 新增上传插件 2020-01-25 20:06:13 +08:00
yanwenwu
6f31f12be7 新增commands 2020-01-25 20:05:57 +08:00
yanwenwu
6b0eb5f849 fixed bugs 2020-01-25 20:03:18 +08:00
yanwenwu
3001ba26b1 修改ignore 2020-01-25 17:07:33 +08:00
yanwenwu
1ce6ddc060 修改composer 2020-01-25 17:07:12 +08:00
yanwenwu
0db7f7d3e9 修改composer 2020-01-25 16:24:44 +08:00
yanwenwu
886e86ef24 修改composer 2020-01-25 16:24:11 +08:00
yanwenwu
44eba6b389 修改权限中间件 2020-01-25 11:34:59 +08:00
yanwenwu
07442c8292 修改权限 2020-01-25 11:20:27 +08:00
yanwenwu
e61b61a220 修改服务 2020-01-24 08:40:04 +08:00
yanwenwu
5450edb490 修改权限中间件 2020-01-24 08:39:52 +08:00
yanwenwu
f8f20ab955 修改权限配置 2020-01-24 08:39:34 +08:00
yanwenwu
bea3e43937 删除不必要的引入 2020-01-23 21:26:45 +08:00
yanwenwu
0708d4ce61 新增ws worker命令 2020-01-23 21:26:30 +08:00
wuyanwen
e1ae8fd084 修改模块创建 2020-01-23 18:21:08 +08:00
wuyanwen
46c7307736 Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2020-01-23 17:16:04 +08:00
wuyanwen
98e74c95dc 修改命令 2020-01-23 17:16:02 +08:00
wuyanwen
7b67e47059 修改rollback 2020-01-23 17:02:03 +08:00
wuyanwen
ac2dab4fa7 删除 2020-01-23 17:01:09 +08:00
yanwenwu
db37e71782 删除viewe目录的生成 2020-01-23 16:57:46 +08:00
yanwenwu
055f3d5aa9 统一命令格式 2020-01-23 16:55:51 +08:00
yanwenwu
cb90f5f6d3 修改migration rollback 2020-01-23 13:18:01 +08:00
wuyanwen
4f5476c270 修改数据填充 2020-01-22 17:56:00 +08:00
wuyanwen
9e4883ead6 增加分页常量 2020-01-21 17:57:33 +08:00
wuyanwen
ac74827130 重写分页方法 2020-01-21 17:56:28 +08:00
wuyanwen
f8a97527f6 修改分页 2020-01-21 17:56:10 +08:00
wuyanwen
5c8072e0b8 修改分页 2020-01-21 17:55:54 +08:00
wuyanwen
9f9a83f157 修改 2020-01-21 17:43:40 +08:00
wuyanwen
a719129b64 修改数据备份 2020-01-21 17:43:09 +08:00
wuyanwen
dfd0be23c6 修改初始化数据 2020-01-21 17:22:51 +08:00
wuyanwen
dc5e46e974 修改服务 2020-01-21 17:00:45 +08:00
wuyanwen
2c732555b0 新增rollback和create migration 命令 2020-01-21 17:00:17 +08:00
wuyanwen
ef545b8732 新增stubs 2020-01-21 16:59:40 +08:00
wuyanwen
b06a5300cb 新增登录退出 2020-01-20 14:38:50 +08:00
wuyanwen
1a03783d26 修改登录和权限路由 2020-01-20 14:38:32 +08:00
wuyanwen
bb372844dc 修改 whereLike 方法 2020-01-20 11:46:32 +08:00
wuyanwen
5f9e90ec67 修改权限管理错误 2020-01-19 15:50:27 +08:00
wuyanwen
257c29391e 修改用户搜索错误 2020-01-19 15:50:15 +08:00
wuyanwen
92d4092f1c 删除冗余路由 2020-01-19 15:49:58 +08:00
wuyanwen
a528ee83ae 修改response返回错误 2020-01-19 15:49:40 +08:00
wuyanwen
d09bcba9f3 修改readme 2020-01-19 15:49:19 +08:00
wuyanwen
4442944cc6 删除不必要的依赖 2020-01-19 09:58:40 +08:00
wuyanwen
51f9873d6e 修改readme 2020-01-17 17:56:54 +08:00
wuyanwen
3e4eca9d45 修改license 2020-01-17 16:07:55 +08:00
wuyanwen
9c7a01406d 修改更新方法 2020-01-17 15:49:42 +08:00
wuyanwen
8b216f2bc4 修改权限 2020-01-17 15:49:29 +08:00
wuyanwen
c6c0446c4e 新增配置 2020-01-17 15:49:18 +08:00
wuyanwen
691518c8c8 修改权限 2020-01-17 15:17:51 +08:00
wuyanwen
fb482ded01 修改request 2020-01-17 11:30:39 +08:00
wuyanwen
f427efd2c8 修改权限 2020-01-17 11:29:33 +08:00
wuyanwen
04d942c7db 缓存用户权限 2020-01-17 11:29:17 +08:00
wuyanwen
7eeade987a 更新框架核心 2020-01-16 14:09:07 +08:00
wuyanwen
5f34bac033 修改composer 2020-01-15 18:11:57 +08:00
wuyanwen
05e22d4db8 修改服务注入 2020-01-14 18:32:30 +08:00
wuyanwen
418a6d5418 修改用户模块 2020-01-14 18:31:18 +08:00
wuyanwen
3983c413f6 修改验证为配置注入 2020-01-14 18:31:08 +08:00
wuyanwen
2acf23d296 修改权限模型 2020-01-14 08:23:29 +08:00
wuyanwen
b6b0b5170d 修改用户模块 2020-01-14 08:23:15 +08:00
wuyanwen
09132deb78 新增角色权限traits 2020-01-14 08:22:53 +08:00
wuyanwen
7e41702de8 修改角色管理 2020-01-14 08:22:31 +08:00
wuyanwen
f63706eb0a 新增addFields方法 2020-01-13 21:40:07 +08:00
wuyanwen
5ba918f1a5 修改部门搜索 2020-01-13 21:39:42 +08:00
wuyanwen
64cd112d43 新增过滤搜索参数方法 2020-01-13 21:24:45 +08:00
wuyanwen
2cc2ecae40 新增query方法 2020-01-13 21:24:27 +08:00
wuyanwen
cffcf11192 新增traits方法 2020-01-13 21:24:12 +08:00
wuyanwen
3e0717c339 新增搜索器 2020-01-13 21:23:45 +08:00
wuyanwen
be02170697 新增搜索器 2020-01-13 21:23:24 +08:00
wuyanwen
3b67f3fb5f 注入Query类 2020-01-13 16:23:08 +08:00
wuyanwen
9e2c84dd54 新增query类 2020-01-13 16:22:16 +08:00
wuyanwen
152cd8738a 修改协议 2020-01-13 07:35:26 +08:00
yanwenwu
0fde164059 修改协议 2020-01-12 12:55:28 +08:00
yanwenwu
1b7cc3fcf5 新增角色部门 2020-01-12 12:54:59 +08:00
JaguarJack
313a396ba8 Update LICENSE.txt 2020-01-12 09:44:37 +08:00
yanwenwu
7c09bcf0cf 新增用户岗位关联表 2020-01-12 09:32:32 +08:00
yanwenwu
8b93c63883 新增部门和岗位 2020-01-12 09:30:56 +08:00
wuyanwen
5ec9939cbf 修改readme 2020-01-09 22:24:06 +08:00
wuyanwen
9673c62a14 修改request 2020-01-09 22:20:57 +08:00
wuyanwen
6cc76c9f8e 修改部门和岗位 2020-01-09 22:20:36 +08:00
wuyanwen
dfcfd78557 修改登录 2020-01-09 22:20:18 +08:00
wuyanwen
e994d14537 去除助手函数 2020-01-09 08:22:50 +08:00
wuyanwen
9bcb7466bd 修改基类 2020-01-09 08:22:38 +08:00
wuyanwen
4fa1c9638e 修改服务 2020-01-09 08:22:25 +08:00
wuyanwen
4387bbb7f9 切换request 2020-01-09 08:22:17 +08:00
wuyanwen
2a805b6709 切换request 2020-01-09 08:21:59 +08:00
wuyanwen
88c3bb432d 新增部门和岗位 2020-01-09 08:21:44 +08:00
wuyanwen
e5c8c71011 修改request 2020-01-08 22:43:40 +08:00
wuyanwen
a5242b3aea 修改request基类 2020-01-08 22:31:17 +08:00
wuyanwen
480aadd38b 修改用户数据 2020-01-08 22:18:04 +08:00
wuyanwen
ca0bf90615 修改权限数据 2020-01-08 22:17:48 +08:00
wuyanwen
2dc1270348 修改yonghu 2020-01-08 22:02:25 +08:00
wuyanwen
ce0eb575e9 修改权限 2020-01-08 22:02:16 +08:00
wuyanwen
a03f3c3699 删除文件 2020-01-07 21:52:38 +08:00
wuyanwen
a041504243 删除助手函数 2020-01-07 21:51:15 +08:00
wuyanwen
3ef506d129 修改readme 2020-01-07 21:50:12 +08:00
wuyanwen
9e28cbd91d 登录 2020-01-07 19:18:24 +08:00
wuyanwen
ba91154ee8 增加auth配置 2020-01-07 19:00:17 +08:00
wuyanwen
cf4ef949b5 修改用户信息 2020-01-07 19:00:04 +08:00
wuyanwen
b41121e35b 修改分享 2020-01-07 18:04:05 +08:00
wuyanwen
c9b39327a5 修改auth认证 2020-01-07 17:27:55 +08:00
wuyanwen
f7ac1a23bf 修改命令 2020-01-06 20:20:24 +08:00
wuyanwen
4a8a0b90e8 delete view 2020-01-06 17:42:51 +08:00
wuyanwen
4bf6d5168f 修改readme 2020-01-06 17:10:34 +08:00
wuyanwen
c53c40487c 修改异常 2020-01-06 17:08:10 +08:00
wuyanwen
9b591340a1 delete 2020-01-06 14:47:21 +08:00
wuyanwen
66e4f8f74f 修改路由规则 2019-12-30 17:45:36 +08:00
wuyanwen
ae084819fe 修改 2019-12-30 17:05:42 +08:00
wuyanwen
b061ab5225 修改服务 2019-12-29 17:01:25 +08:00
wuyanwen
872f6b9dfb 增加icon 2019-12-29 17:01:06 +08:00
root
9988c7c00c 删除静态文件 2019-12-29 08:31:14 +08:00
wuyanwen
ef44acee7a 编辑未初始化数据BUG 2019-12-29 08:17:29 +08:00
wuyanwen
998c8edf24 修改服务 2019-12-29 07:48:59 +08:00
wuyanwen
b2bdb12e5b 修改生产的api 2019-12-28 22:19:05 +08:00
wuyanwen
06726f8fc0 修改权限 2019-12-28 21:21:05 +08:00
wuyanwen
1798cbcd0c 修改权限 2019-12-28 21:20:27 +08:00
wuyanwen
a634aa4f93 新增系统模块 2019-12-27 17:01:32 +08:00
wuyanwen
fcc2e04b85 修改 2019-12-27 15:56:56 +08:00
wuyanwen
ef30c07f4a 修改权限 2019-12-27 09:52:03 +08:00
wuyanwen
b94800033f 修改类库 2019-12-27 09:51:48 +08:00
wuyanwen
201cb455f5 修改类库 2019-12-26 09:03:19 +08:00
wuyanwen
1dcce85c3a 修改权限管理 2019-12-26 09:03:09 +08:00
wuyanwen
4a3f043166 角色和用户管理 2019-12-25 22:12:16 +08:00
wuyanwen
ceda3a224a 修改 2019-12-24 18:21:57 +08:00
wuyanwen
8d5ec7966a 修改依赖 2019-12-23 08:40:42 +08:00
wuyanwen
2dc5321128 delete views 2019-12-22 22:04:01 +08:00
yanwenwu
a258ba6cc2 修改用户 2019-12-22 14:18:21 +08:00
yanwenwu
b27ef2570a first commit 2019-12-22 09:37:52 +08:00
999 changed files with 26716 additions and 66237 deletions

View File

@@ -0,0 +1,24 @@
# 环境
- 操作系统:
- php 版本:
- thinkphp 版本:
- Mysql 版本:
- web 服务器:
# 问题
- 问题描述:
- 问题截图:
# 结果
- 实际结果:
- 预期结果:
# 分析
- 所做的尝试:
-
-
# 方案:
- 解决方案:
> 请在问题解决后关闭 issue

25
.github/issue_template.md vendored Normal file
View File

@@ -0,0 +1,25 @@
# 环境
- 操作系统:
- php 版本:
- thinkphp 版本:
- Mysql 版本:
- web 服务器:
# 问题
- 问题描述:
- 问题截图:
# 结果
- 实际结果:
- 预期结果:
# 分析
- 所做的尝试:
-
-
# 方案:
- 解决方案:
> 请在问题解决后关闭 issue

4
.gitignore vendored
View File

@@ -1,6 +1,8 @@
/.idea /.idea
/.vscode /.vscode
/vendor /vendor
/database /package
*.log *.log
.env .env
composer.lock

View File

@@ -1,32 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
ThinkPHP遵循Apache2开源协议发布并提供免费使用。 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。 1. Definitions.
该协议和BSD类似鼓励代码共享和尊重原作者的著作权
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1 需要给代码的用户一份Apache Licence
2 如果你修改了代码,需要在被修改的文件中说明;
3 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4 如果再发布的产品中包含一个Notice文件则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可但不可以表现为对Apache Licence构成更改。
具体的协议参考http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "License" shall mean the terms and conditions for use, reproduction,
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT and distribution as defined by Sections 1 through 9 of this document.
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE "Licensor" shall mean the copyright owner or entity authorized by
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, the copyright owner that is granting the License.
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; "Legal Entity" shall mean the union of the acting entity and all
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER other entities that control, are controlled by, or are under common
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT control with that entity. For the purposes of this definition,
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN "control" means (i) the power, direct or indirect, to cause the
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE direction or management of such entity, whether by contract or
POSSIBILITY OF SUCH DAMAGE. otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

180
README.md
View File

@@ -1,47 +1,161 @@
## CatchAdmin <p align="center">
<img src="https://cdn.learnku.com/uploads/images/202005/17/18206/zSuf7Ce5kM.png!large">
</p>
## 5.1 版本的请使用 tag1.0 版本
## 新版后台在开发中 请不要使用 <p align="center"><code>CatchAdmin</code>是一款基于<a href="http://www.thinkphp.cn/" target="_blank">thinkphp framework</a>
### 环境要求 <a href="https://github.com/PanJiaChen/vue-element-admin/">element admin</a>二次开发而成后台管理系统。因为 thinkphp 的简单高效,文档齐全。在看了很多 thinkphp 生态中的后台管理系统,发现没有一款合适的前后端分离系统。遂开发了 CatchAdmin。
完全利用了 thinkphp6 的新版本特性 ServiceProvider将管理系统模块之间的耦合降到了最低限度。每个模块之间都有独立的 controller路由模型数据表`。在开发上尽可能将模块之间的影响降到最低,降低了开发上的难度。基于 CatchAdmin 可以开发 cmsCRMOA 等
等系统。也封装了很多实用的工具,提升开发体验。
</p>
<p align="center">
<a href="http://doc.catchadmin.com/">文档</a> |
<a href="http://vue.catchadmin.com">演示地址</a> |
<a href="http://apidoc.catchadmin.com">接口文档</a> |
<a href="https://gitee.com/jaguarjack/catchAdmin">项目源码</a> |
<a href="https://www.kancloud.cn/akasishikelu/thinkphp6">看云分析</a>
<a href="#extensions">扩展</a>
</p>
<p align="center">
<a href="https://gitee.com/jaguarjack/catchAdmin" target="_blank">
<img src="https://svg.hamm.cn/gitee.svg?type=star&user=jaguarjack&project=catchAdmin"/>
</a >
<a href="https://gitee.com/jaguarjack/catchAdmin" target="_blank">
<img src="https://svg.hamm.cn/gitee.svg?type=fork&user=jaguarjack&project=catchAdmin"/>
</a >
<img src="https://svg.hamm.cn/badge.svg?key=Base&value=ThinkPHP6"/>
<img src="https://svg.hamm.cn/badge.svg?key=Data&value=MySQL5.5"/>
<img src="https://svg.hamm.cn/badge.svg?key=Runtime&value=PHP7.1"/>
<img src="https://svg.hamm.cn/badge.svg?key=License&value=Apache-2.0"/>
</p >
## AntDV 版本
- 请使用 `v1`分支
## 功能
- [x] `用户管理` 后台用户管理
- [x] `部门管理` 配置公司的部门结构,支持树形结构
- [x] `岗位管理` 配置后台用户的职务
- [x] `菜单管理` 配置系统菜单,按钮等等
- [x] `角色管理` 配置用户担当的角色,分配权限
- [x] `数据字典` 管理后台表结构
- [x] `操作日志` 后台用户操作记录
- [x] `登录日志` 后台系统用户的登录记录
- [x] `代码生成` 生成 API 端的 CURD 操作
- [x] `敏感词` 支持敏感词配置
- [x] `附件管理` 可管理上传的文件
- [x] `定时任务` 可管理定时任务,而不依赖于 Crontab
- [x] `短信平台` 短信云管理,支持 阿里大于腾讯云UcloudSubmail
- [x] `云上传` 支持云上传七牛OSS腾讯
- [ ] `微信管理`
## 项目地址
- [github 地址](https://github.com/yanwenwu/catch-admin)
- [gitee 地址](https://gitee.com/jaguarjack/catchAdmin)
- [前端 Vue 项目地址](https://github.com/yanwenwu/catch-admin-vue)
- [文档地址](https://github.com/catch-admin/document)[个人精力实在有限,希望可以小伙伴们可以一起维护文档]
## 预览
<table>
<tr>
<td><img src="https://s1.ax1x.com/2020/09/07/wucNXq.md.png"></td>
<td><img src="https://s1.ax1x.com/2020/09/07/wucm6I.md.png"></td>
</tr>
<tr>
<td><img src="https://s1.ax1x.com/2020/09/07/wucZpd.md.png"></td>
<td><img src="https://s1.ax1x.com/2020/09/07/wuce1A.md.png"></td>
</tr>
<tr>
<td><img src="https://s1.ax1x.com/2020/09/07/wucnXt.md.png"></td>
<td><img src="https://s1.ax1x.com/2020/09/07/wucKnP.md.png"></td>
</tr>
<tr>
<td><img src="https://s1.ax1x.com/2020/09/07/wuc3tg.md.png"></td>
<td><img src="https://s1.ax1x.com/2020/09/07/wucM0f.md.png"></td>
</tr>
<tr>
<td><img src="https://s1.ax1x.com/2020/09/07/wucQ78.md.png"></td>
<td><img src="https://s1.ax1x.com/2020/09/07/wuc1AS.md.png"></td>
</tr>
<tr>
<td><img src="https://s1.ax1x.com/2020/09/07/wuc8hQ.md.png"></td>
<td><img src="https://s1.ax1x.com/2020/09/07/wucY1s.md.png"></td>
</tr>
<tr>
<td><img src="https://s1.ax1x.com/2020/09/07/wucJpj.md.png"></td>
<td><img src="https://s1.ax1x.com/2020/09/07/wuctcn.md.png"></td>
</tr>
</table>
## 环境要求
- php7.1+ (需以下扩展) - php7.1+ (需以下扩展)
- mbstring - [x] mbstring
- json - [x] json
- openssl - [x] openssl
- xml - [x] xml
- pdo - [x] pdo
- nginx - nginx
- mysql - mysql
### install ### 如何安装
- curl -sS http://install.phpcomposer.com/installer | php > 安装之前请确保已安装 Composer
- composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
- composer update
- php think catch:install
### Use #### 下载项目
- 配置虚拟域名 OR 在根目录下执行 php think run - 通过 Git 下载(推荐)
- yourUrl/login ```shell
- 默认用户名 admin@gmail.com 密码 admin git clone https://gitee.com/jaguarjack/catchAdmin && cd catchAdmin
### Problem curl -sS https://install.phpcomposer.com/installer | php
> SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'updated_at'
> 设置 sql_mode; composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
composer install --ignore-platform-reqs
``` ```
show variables like 'sql_mode' ; - composer 安装
remove 'NO_ZERO_IN_DATE,NO_ZERO_DATE' ```shell
composer create-project jaguarjack/catchadmin:dev-master
``` ```
> SET GLOBAL sql_mode='STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
### Talking #### 安装
- 可以提 ISSUE请按照 issue 模板提问 下载完成之后通过命令来进行安装, 一键安装 🚀
- 欢迎进入 Q 群,可以及时反馈一些问题。 ```shell
- ![输入图片说明](https://images.gitee.com/uploads/images/2018/1219/110300_0257b6c0_810218.jpeg "微信图片_20181219105915.jpg") php think catch:install
```
仅供学习
## 体验地址 ## 体验地址
[体验地址](http://catch.njphper.com/login) [体验地址](http://vue.catchadmin.com)
- 账号: test@catch.com - 账号: catch@admin.com
- 密码: 123456 - 密码: catchadmin
[catchadmin 文档地址](http://doc.catchadmin.com)
### 系列文章
如果是刚开始使用 thinkphp6, 以下文章可能会对你有些许帮助,文章基于 RC3 版本。整体架构是不变的。
- [Tp6 启动分析](https://www.kancloud.cn/akasishikelu/thinkphp6/1129385)
- [Tp6 Request 解析](https://www.kancloud.cn/akasishikelu/thinkphp6/1134496)
- [TP6 应用初始化](https://www.kancloud.cn/akasishikelu/thinkphp6/1130427)
- [Tp6 中间件分析](https://www.kancloud.cn/akasishikelu/thinkphp6/1136616)
- [Tp6 请求流程](https://www.kancloud.cn/akasishikelu/thinkphp6/1136608)
### Donate
如果你觉得项目对你有帮助,可以请作者喝杯咖啡☕️!鼓励下
<img src="https://cdn.learnku.com/uploads/images/202008/11/18206/e6qAAM8Bod.jpg!large">
### Talking
- [论坛讨论](http://bbs.catchadmin.com)
- 可以提 `ISSUE`,请按照 `issue` 模板提问
- 加入 Q 群 `302266230` 前请先 star 项目支持一下, 备注填写用户名 + 平台。例如: JaguarJack Github
### Thanks
- 感谢 [JetBrains](https://www.jetbrains.com) 提供生产力巨高的 `PHPStorm`和`WebStorm`
> 排名部分先后
- [top-think/think](https://github.com/top-think/think)
- [element-admin](https://panjiachen.gitee.io/vue-element-admin-site/zh/)
- [thans/tp-jwt-auth](https://packagist.org/packages/thans/tp-jwt-auth)
- [jaguarjack/think-filesystem-cloud](https://github.com/yanwenwu/think-filesystem-cloud)
- [overtrue/wechat](https://github.com/overtrue/wechat)
- [jaguarjack/migration-generator](https://github.com/yanwenwu/migration-generator)
- [phpoffice/phpspreadsheet](https://github.com/PHPOffice/PhpSpreadsheet)

View File

@@ -3,11 +3,8 @@ declare (strict_types = 1);
namespace app; namespace app;
use catcher\CatchAdmin;
use think\App; use think\App;
use think\exception\ValidateException; use think\exception\ValidateException;
use think\facade\View;
use think\helper\Str;
use think\Validate; use think\Validate;
/** /**

View File

@@ -1,11 +1,6 @@
<?php <?php
namespace app; namespace app;
use catcher\CatchResponse;
use catcher\exceptions\CatchException;
use catcher\exceptions\FailedException;
use catcher\exceptions\LoginFailedException;
use catcher\exceptions\PermissionForbiddenException;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
use think\exception\Handle; use think\exception\Handle;
@@ -56,10 +51,7 @@ class ExceptionHandle extends Handle
*/ */
public function render($request, Throwable $e): Response public function render($request, Throwable $e): Response
{ {
// if ($e instanceof CatchException){
return CatchResponse::fail($e->getMessage(), $e->getCode());
// }
// 其他错误交给系统处理 // 其他错误交给系统处理
//return parent::render($request, $e); return parent::render($request, $e);
} }
} }

View File

@@ -3,12 +3,51 @@ namespace app;
// 应用请求对象类 // 应用请求对象类
use catchAdmin\user\Auth; use catchAdmin\permissions\model\Users;
use catcher\CatchAuth;
use catcher\Code;
use catcher\exceptions\FailedException;
use catcher\exceptions\LoginFailedException;
use thans\jwt\exception\TokenBlacklistException;
use thans\jwt\exception\TokenExpiredException;
use thans\jwt\exception\TokenInvalidException;
class Request extends \think\Request class Request extends \think\Request
{ {
public function user() protected $auth;
/**
* login user
*
* @time 2020年01月09日
* @param null $guard
* @return mixed
*/
public function user($guard = null)
{ {
return Auth::user(); if (!$this->auth) {
$this->auth = new CatchAuth;
}
try {
$user = $this->auth->guard($guard ? : config('catch.auth.default.guard'))->user();
if ($user->status == Users::DISABLE) {
throw new LoginFailedException('该用户已被禁用', Code::USER_FORBIDDEN);
}
} catch (\Exception $e) {
if ($e instanceof TokenExpiredException) {
throw new FailedException('token 过期', Code::LOGIN_EXPIRED);
}
if ($e instanceof TokenBlacklistException) {
throw new FailedException('token 被加入黑名单', Code::LOGIN_BLACKLIST);
}
if ($e instanceof TokenInvalidException) {
throw new FailedException('token 不合法', Code::LOST_LOGIN);
}
throw new FailedException('认证失败: '. $e->getMessage(), $e->getCode());
}
return $user;
} }
} }

View File

@@ -6,5 +6,6 @@ return [
// 多语言加载 // 多语言加载
// \think\middleware\LoadLangPack::class, // \think\middleware\LoadLangPack::class,
// Session初始化 // Session初始化
\think\middleware\SessionInit::class // \think\middleware\SessionInit::class
\think\middleware\AllowCrossDomain::class,
]; ];

View File

@@ -1,5 +1,4 @@
<?php <?php
return [ return [
\jaguarjack\think\module\ThinkModuleService::class, \catcher\CatchAdminService::class,
\catchAdmin\CatchAdminService::class,
]; ];

BIN
catch/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,53 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain;
use catchAdmin\domain\support\contract\DomainActionInterface;
use catchAdmin\domain\support\contract\DomainRecordInterface;
use catchAdmin\domain\support\driver\aliyun\Domain;
use catchAdmin\domain\support\driver\aliyun\DomainRecord;
use catcher\ModuleService;
class DomainService extends ModuleService
{
public function register()
{
parent::register(); // TODO: Change the autogenerated stub
$this->registerInstance();
}
public function loadConfig()
{
return require __DIR__ . DIRECTORY_SEPARATOR . 'config.php';
}
/**
* @return string
*/
public function loadRouteFrom()
{
// TODO: Implement loadRouteFrom() method.
return __DIR__ . DIRECTORY_SEPARATOR . 'route.php';
}
/**
*
*/
protected function registerInstance()
{
$default = config('catch.domains.default');
$this->app->instance(DomainActionInterface::class, $this->app->make(__NAMESPACE__ . '\\support\\driver\\' . $default . '\Domain'));
$this->app->instance(DomainRecordInterface::class, $this->app->make(__NAMESPACE__ . '\\support\\driver\\' . $default . '\DomainRecord'));
}
}

46
catch/domain/README.md Normal file
View File

@@ -0,0 +1,46 @@
## 域名管理
- 阿里云(主支持)
- 腾讯云(需要做适配)
#### 配置
首先在 .env 文件设置
```
[ALIYUN]
ACCESS_KEY=
ACCESS_SECRET=
[QCLOUD]
ACCESS_KEY=
ACCESS_SECRET=
```
也可以在 config.php 文件配置
```
'domains' => [
// 默认阿里云
'default' => 'aliyun',
/**
* 阿里云配置
*
*/
'aliyun' => [
'api_domain' => 'http://alidns.aliyuncs.com',
'access_key' => Env::get('aliyun.access_key', ''),
'access_secret' => Env::get('aliyun.access_secret', ''),
],
/**
* 腾讯云配置
*
*/
'qcloud' => [
'api_domain' => 'cns.api.qcloud.com',
'access_key' => Env::get('qcloud.access_key', ''),
'access_secret' => Env::get('qcloud.access_secret', ''),
]
]
```

43
catch/domain/config.php Normal file
View File

@@ -0,0 +1,43 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
use think\facade\Env;
return [
'domains' => [
// 默认阿里云
'default' => 'aliyun',
/**
* 阿里云配置
*
*/
'aliyun' => [
'api_domain' => 'http://alidns.aliyuncs.com',
'access_key' => Env::get('aliyun.access_key', ''),
'access_secret' => Env::get('aliyun.access_secret', ''),
],
/**
* 腾讯云配置
*
*/
'qcloud' => [
'api_domain' => 'cns.api.qcloud.com',
'access_key' => Env::get('qcloud.access_key', ''),
'access_secret' => Env::get('qcloud.access_secret', ''),
]
]
];

View File

@@ -0,0 +1,50 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\controller;
use catchAdmin\domain\support\contract\DomainActionInterface;
use catcher\base\CatchRequest as Request;
use catcher\CatchResponse;
use catcher\base\CatchController;
class Domain extends CatchController
{
protected $domain;
public function __construct(DomainActionInterface $domain)
{
$this->domain = $domain;
}
/**
* 列表
*
* @time 2020/09/11 18:14
* @param Request $request
* @return \think\Response
*/
public function index(Request $request): \think\Response
{
return CatchResponse::paginate($this->domain->getList($request->param()));
}
/**
* 读取
*
* @time 2020/09/11 18:14
* @param $name
* @return \think\Response
*/
public function read($name)
{
return CatchResponse::success($this->domain->read(str_replace('-', '.', $name)));
}
}

View File

@@ -0,0 +1,99 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\controller;
use catchAdmin\domain\support\contract\DomainRecordInterface;
use catcher\base\CatchRequest as Request;
use catcher\CatchResponse;
use catcher\base\CatchController;
class DomainRecord extends CatchController
{
protected $domainRecord;
public function __construct(DomainRecordInterface $record)
{
$this->domainRecord = $record;
}
/**
* 列表
*
* @time 2020/09/11 18:14
* @param Request $request
* @return \think\Response
*/
public function index(Request $request): \think\Response
{
return CatchResponse::paginate($this->domainRecord->getList($request->param()));
}
/**
* 保存
*
* @time 2020/09/11 18:14
* @param Request Request
* @return \think\Response
*/
public function save(Request $request): \think\Response
{
return CatchResponse::success($this->domainRecord->store($request->post()));
}
/**
* 读取
*
* @time 2020/09/11 18:14
* @param $name
* @return \think\Response
*/
public function read($name): \think\Response
{
return CatchResponse::success($this->domainRecord->read($name));
}
/**
* 更新
*
* @time 2020/09/11 18:14
* @param Request $request
* @param $id
* @return \think\Response
*/
public function update($id, Request $request): \think\Response
{
return CatchResponse::success($this->domainRecord->update($id, $request->post()));
}
/**
* 删除
*
* @time 2020/09/11 18:14
* @param $id
* @return \think\Response
*/
public function delete($id): \think\Response
{
return CatchResponse::success($this->domainRecord->delete($id));
}
/**
* 设置状态
*
* @param $id
* @param $status
* @return \think\response\Json
*/
public function enable($id, $status)
{
return CatchResponse::success($this->domainRecord->enable($id, $status));
}
}

View File

@@ -0,0 +1,97 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
use think\migration\Seeder;
class DomainMenusSeed extends Seeder
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* http://docs.phinx.org/en/latest/seeding.html
*/
public function run()
{
\catcher\Utils::importTreeData($this->getPermissions(), 'permissions', 'parent_id');
}
protected function getPermissions()
{
return array (
0 =>
array (
'id' => 72,
'permission_name' => '域名管理',
'parent_id' => 0,
'level' => '',
'route' => '/domain',
'icon' => 'el-icon-stopwatch',
'module' => 'domain',
'creator_id' => 1,
'permission_mark' => 'domain',
'component' => 'layout',
'redirect' => '/domain/index',
'keepalive' => 1,
'type' => 1,
'hidden' => 1,
'sort' => 1,
'created_at' => 1601105834,
'updated_at' => 1601105834,
'deleted_at' => 0,
),
1 =>
array (
'id' => 73,
'permission_name' => '域名设置',
'parent_id' => 72,
'level' => '72',
'route' => '/domain/index',
'icon' => 'el-icon-setting',
'module' => 'domain',
'creator_id' => 1,
'permission_mark' => 'domain',
'component' => 'domain',
'redirect' => '',
'keepalive' => 1,
'type' => 1,
'hidden' => 1,
'sort' => 8,
'created_at' => 1601105879,
'updated_at' => 1601112604,
'deleted_at' => 0,
),
2 =>
array (
'id' => 84,
'permission_name' => '域名记录',
'parent_id' => 72,
'level' => '72',
'route' => '/domain/record/:domain',
'icon' => 'el-icon-document',
'module' => 'domain',
'creator_id' => 1,
'permission_mark' => 'domainRecord',
'component' => 'domainRecord',
'redirect' => '',
'keepalive' => 1,
'type' => 1,
'hidden' => 2,
'sort' => 1,
'created_at' => 1601112569,
'updated_at' => 1601112606,
'deleted_at' => 0,
),
);
}
}

15
catch/domain/module.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "域名管理",
"alias": "domain",
"description": "域名,阿里云,腾讯云",
"version": "1.0.0",
"keywords": [],
"order": 0,
"services": [
"\\catchAdmin\\domain\\DomainService"
],
"aliases": {},
"files": [],
"requires": [],
"enable": false
}

23
catch/domain/route.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
// you should use `$router`
use catchAdmin\domain\controller\DomainRecord;
$router->group(function () use ($router){
// 域名管理
$router->get('domain', '\catchAdmin\domain\controller\Domain@index');
$router->get('domain/<name>', '\catchAdmin\domain\controller\Domain@read');
// 域名解析管理
$router->resource('record/domain', DomainRecord::class);
$router->put('record/domain/<id>/<status>', '\catchAdmin\domain\controller\DomainRecord@enable');
})->middleware('auth');

View File

@@ -0,0 +1,70 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support;
use catchAdmin\domain\support\signature\Aliyun;
use catchAdmin\domain\support\signature\Qcloud;
/**
* 公共参数
*
* Class CommonParams
* @package catchAdmin\domain\support
*/
class CommonParams
{
/**
* 阿里云公共参数
*
* @param array $params
* @param string $method
* @return array
*/
public static function aliyun(array $params, $method = 'GET')
{
date_default_timezone_set('UTC');
$params = array_merge($params, [
'Format' => 'json',
'Version' => '2015-01-09',
'AccessKeyId' => config('catch.domains.aliyun.access_key'),
'SignatureMethod' => 'HMAC-SHA1',
'Timestamp' => date('Y-m-d\TH:i:s\Z'),
'SignatureVersion' => '1.0',
'SignatureNonce' => uniqid()
]);
$params['Signature'] = (new Aliyun($params))->signature($method);
return $params;
}
/**
* 腾讯云公共参数
*
* @param array $params
* @param string $method
* @return array
*/
public static function qcloud(array $params, $method = 'GET')
{
$params = array_merge($params, [
'SecretId' => config('catch.domains.qcloud.access_key'),
'SignatureMethod' => 'HmacSHA1',
'Timestamp' => time(),
'Nonce' => uniqid()
]);
$params['Signature'] = (new Qcloud($params))->signature($method);
return $params;
}
}

View File

@@ -0,0 +1,112 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support;
use think\Paginator;
class Transformer
{
/**
* 分页展示
*
* @param array $data
* @return mixed
*/
public static function aliyunDomainPaginate(array $data)
{
$list = [];
foreach ($data['Domains']['Domain'] as $item) {
$list[] = [
'name' => $item['DomainName'],
'created_at' => date('Y-m-d', $item['CreateTimestamp']/1000),
'dns_server' => $item['DnsServers']['DnsServer'],
'from' => $item['VersionName'],
'free' => $item['VersionCode'] === 'mianfei',
'record_count' => $item['RecordCount'],
'tags' => $item['Tags']['Tag'],
'id' => $item['DomainId']
];
}
return Paginator::make($list, $data['PageSize'], $data['PageNumber'], $data['TotalCount']);
}
/**
* 腾讯云域名列表
*
* @param array $data
* @param $page
* @param $limit
* @return Paginator|\think\paginator\driver\Bootstrap
*/
public static function qcloudDomainPaginate(array $data, $page, $limit)
{
$info = $data['data']['info'];
$domains = $data['data']['domains'];
$list = [];
foreach ($domains as $item) {
$list[] = [
'name' => $item['name'],
'created_at' => $item['created_on'],
'dns_server' => [],
'from' => 'qcloud',
'free' => $item['grade'] === 'DP_Free',
'record_count' => $item['records'],
'tags' => [],
'id' => $item['id']
];
}
return Paginator::make($list, $limit, $page + 1,$info['domain_total']);
}
/**
* 阿里云域名解析
*
* @param array $data
* @return mixed
*/
public static function aliyunDomainRecordPaginate(array $data)
{
$list = [];
foreach ($data['DomainRecords']['Record'] as &$item) {
$list[] = array_change_key_case($item);
}
return Paginator::make($list, $data['PageSize'], $data['PageNumber'], $data['TotalCount']);
}
/**
* DNS 记录
*
* @param array $data
* @param $page
* @param $limit
* @return Paginator|\think\paginator\driver\Bootstrap
*/
public static function qcloudDomainRecordPaginate(array $data, $page, $limit)
{
$list = [];
foreach ($data['data']['records'] as &$item) {
$item['status'] = $item['status'] === 'enabled' ? 'ENABLE' : 'DISABLE';
$item['rr'] = $item['name'];
$item['recordid'] = $item['id'];
$list[] = array_change_key_case($item);
}
return Paginator::make($list, $limit, $page + 1, $data['data']['info']['record_total']);
}
}

View File

@@ -0,0 +1,22 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\contract;
interface DomainActionInterface
{
public function getList(array $params);
public function store(array $params);
public function delete(array $params);
public function read($name);
}

View File

@@ -0,0 +1,27 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\contract;
interface DomainRecordInterface
{
public function getList(array $params);
public function store(array $params);
public function delete($recordId);
public function read(array $params);
public function update($recordId, array $params);
public function enable($recordId, $status);
}

View File

@@ -0,0 +1,32 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\driver;
use catcher\facade\Http;
use catchAdmin\domain\support\CommonParams;
trait ApiTrait
{
public function get(array $params)
{
$name = config('catch.domains.default');
$apiDomain = config('catch.domains.' . $name . '.api_domain');
if (strpos($apiDomain, 'https') === false &&
strpos($apiDomain, 'http') === false) {
$apiDomain = 'https://' . $apiDomain . '/v2/index.php';
}
return Http::ignoreSsl()->query(CommonParams::{$name}($params))
->get($apiDomain)->json();
}
}

View File

@@ -0,0 +1,55 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\driver\aliyun;
use catchAdmin\domain\support\contract\DomainActionInterface;
use catchAdmin\domain\support\driver\ApiTrait;
use catchAdmin\domain\support\Transformer;
class Domain implements DomainActionInterface
{
use ApiTrait;
public function getList(array $params)
{
// TODO: Implement getList() method.
return Transformer::aliyunDomainPaginate($this->get([
'Action' => 'DescribeDomains',
'StarMark' => true,
'SearchModel' => 'LIKE',
'PageNumber' => $params['page'] ?? 1,
'PageSize' => $params['limit'] ?? 20,
]));
}
public function store(array $params)
{
// TODO: Implement add() method.
}
public function delete(array $params)
{
// TODO: Implement delete() method.
return $this->get([
'Action' => 'DeleteDomain',
'DomainName' => $params['name'],
]);
}
public function read($name)
{
// TODO: Implement info() method.
return $this->get([
'Action' => 'DescribeDomainInfo',
'DomainName' => $name
]);
}
}

View File

@@ -0,0 +1,147 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\driver\aliyun;
use catchAdmin\domain\support\contract\DomainRecordInterface;
use catchAdmin\domain\support\driver\ApiTrait;
use catchAdmin\domain\support\Transformer;
class DomainRecord implements DomainRecordInterface
{
use ApiTrait;
/**
* 列表
*
* @param array $params
* @return mixed
*/
public function getList(array $params)
{
$data = [
'Action' => 'DescribeDomainRecords',
'DomainName' => $params['name'],
'PageNumber' => $params['page'] ?? 1,
'PageSize' => $params['limit'] ?? 20,
];
if ($params['rr']) {
$data['RRKeyWord'] = $params['rr'];
}
if ($params['type']) {
$data['TypeKeyWord'] = $params['type'];
}
if ($params['value']) {
$data['ValueKeyWord'] = $params['value'];
}
if ($params['line']) {
$data['Line'] = $params['line'];
}
if ($params['status']) {
$data['Status'] = $params['status'];
}
// TODO: Implement getList() method.
return Transformer::aliyunDomainRecordPaginate($this->get($data));
}
/**
* 新增解析
*
* @param array $params
* @return array
*
*/
public function store(array $params)
{
// TODO: Implement add() method.
return $this->get([
'Action' => 'AddDomainRecord',
'DomainName' => $params['name'],
'RR' => $params['rr'],
'Type' => $params['type'],
'Value' => $params['value'],
'Line' => $params['line'],
'TTL' => $params['ttl'],
]);
}
/**
* 删除解析
*
* @param $recordId
* @return array
*/
public function delete($recordId)
{
// TODO: Implement delete() method.
return $this->get([
'Action' => 'DeleteDomainRecord',
'RecordId' => $recordId
]);
}
/**
* 获取解析记录
*
* @param array $params
* @return array
*/
public function read(array $params)
{
// TODO: Implement info() method.
return $this->get([
'Action' => 'DescribeDomainRecord',
'RecordId' => $params['record_id'],
]);
}
/**
* 更新解析
*
* @param array $params
* @param $recordId
* @return array
*/
public function update($recordId, array $params)
{
// TODO: Implement update() method.
return $this->get([
'Action' => 'UpdateDomainRecord',
'RecordId' => $recordId,
'RR' => $params['rr'],
'Type' => $params['type'],
'Value' => $params['value'],
'Line' => $params['line'],
'TTL' => $params['ttl'],
]);
}
/**
* 设置状态
*
* @param $recordId
* @param $status
* @return array
*/
public function enable($recordId, $status)
{
return $this->get([
'Action' => 'SetDomainRecordStatus',
'RecordId' => $recordId,
'Status' => ucfirst(strtolower($status))
]);
}
}

View File

@@ -0,0 +1,56 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\driver\qcloud;
use catchAdmin\domain\support\contract\DomainActionInterface;
use catchAdmin\domain\support\driver\ApiTrait;
use catchAdmin\domain\support\Transformer;
class Domain implements DomainActionInterface
{
use ApiTrait;
public function getList(array $params)
{
$offset = ($params['page'] ?? 1) - 1;
$length = $params['limit'] ?? 10;
// TODO: Implement getList() method.
return Transformer::qcloudDomainPaginate($this->get([
'Action' => 'DomainList',
'offset' => $offset,
'length' => $length
]), $offset, $length);
}
public function store(array $params)
{
// TODO: Implement add() method.
}
public function delete(array $params)
{
// TODO: Implement delete() method.
return $this->get([
'Action' => 'DeleteDomain',
'DomainName' => $params['name'],
]);
}
public function read($name)
{
// TODO: Implement info() method.
return $this->get([
'Action' => 'DescribeDomainInfo',
'DomainName' => $name
]);
}
}

View File

@@ -0,0 +1,125 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\driver\qcloud;
use catchAdmin\domain\support\contract\DomainRecordInterface;
use catchAdmin\domain\support\driver\ApiTrait;
use catchAdmin\domain\support\Transformer;
class DomainRecord implements DomainRecordInterface
{
use ApiTrait;
/**
* 列表
*
* @param array $params
* @return mixed
*/
public function getList(array $params)
{
$data = [
'Action' => 'RecordList',
'domain' => $params['name'],
'offset' => ($params['page'] ?? 1) - 1,
'length' => $params['limit'] ?? 10,
];
if ($params['rr']) {
$data['subDomain'] = $params['rr'];
}
if ($params['type']) {
$data['recordType'] = $params['type'];
}
// TODO: Implement getList() method.
return Transformer::qcloudDomainRecordPaginate($this->get($data), $data['offset'], $data['length']);
}
/**
* 新增解析
*
* @param array $params
* @return array
*
*/
public function store(array $params)
{
// TODO: Implement add() method.
return $this->get([
'Action' => 'RecordCreate',
'domain' => $params['name'],
'subDomain' => $params['rr'],
'recordType' => $params['type'],
'value' => $params['value'],
'recordLine' => $params['line'],
'ttl' => $params['ttl'],
]);
}
/**
* 删除解析
*
* @param $recordId
* @return array
*/
public function delete($recordId)
{
// TODO: Implement delete() method.
return $this->get([
'Action' => 'RecordDelete',
'recordId' => $recordId
]);
}
/**
* 更新解析
*
* @param array $params
* @param $recordId
* @return array
*/
public function update($recordId, array $params)
{
// TODO: Implement update() method.
return $this->get([
'Action' => 'RecordModify',
'recordId' => $recordId,
'subDomain' => $params['rr'],
'recordType' => $params['type'],
'value' => $params['value'],
'recordLine' => $params['line'],
'ttl' => $params['ttl'],
]);
}
/**
* 设置状态
*
* @param $recordId
* @param $status
* @return array
*/
public function enable($recordId, $status)
{
return $this->get([
'Action' => 'RecordStatus',
'recordId' => $recordId,
'Status' => strtolower($status)
]);
}
public function read(array $params)
{
// TODO: Implement read() method.
}
}

View File

@@ -0,0 +1,64 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\signature;
class Aliyun
{
/**
* @var array
*/
protected $params;
/**
* Aliyun constructor.
* @param $params
*/
public function __construct(array $params)
{
$this->params = $params;
}
/**
* encode
*
* @time 2020年09月25日
* @param $str
* @return string|string[]|null
*/
protected function percentEncode(string $str)
{
return preg_replace(['/\+/', '/\*/', '/%7E/'], ['%20', '%2A', '~'], urlencode($str));
}
/**
* 签名
*
* @time 2020年09月25日
* @param $method
* @return string
*/
public function signature(string $method)
{
ksort($this->params);
$queryString = '';
foreach ($this->params as $key => $param) {
$queryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($param);
}
$signString = $method . '&' .
$this->percentEncode('/') . '&' .
$this->percentEncode(substr($queryString, 1));
return base64_encode(hash_hmac('sha1', $signString, config('catch.domains.aliyun.access_secret'). '&', true));
}
}

View File

@@ -0,0 +1,63 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\signature;
class Qcloud
{
/**
* @var array
*/
protected $params;
/**
* Qcloud constructor.
* @param $params
*/
public function __construct(array $params)
{
$this->params = $params;
}
/**
* key 替换
*
* @param $key
* @return mixed|string|string[]
*/
protected function replaceKey($key)
{
return strpos($key, '_') === false ?
$key : str_replace('_', '.', $key);
}
/**
* 签名
*
* @time 2020年09月25日
* @param $method
* @return string
*/
public function signature(string $method)
{
ksort($this->params);
$queryString = '';
foreach ($this->params as $key => $param) {
$queryString .= '&' . $this->replaceKey($key) . '=' . $param;
}
$signString = $method . config('catch.domains.qcloud.api_domain') . '/v2/index.php?'
. substr($queryString, 1);
return base64_encode(hash_hmac('sha1', $signString, config('catch.domains.qcloud.access_secret'), true));
}
}

View File

@@ -1,24 +1,23 @@
<?php <?php
namespace catchAdmin\login; namespace catchAdmin\login;
use catchAdmin\user\model\Users; use catchAdmin\permissions\model\Users;
use catchAdmin\system\model\LoginLog;
use think\facade\Db; use think\facade\Db;
class LoginLogListener class LoginLogEvent
{ {
public function handle($params) public function handle($params)
{ {
$agent = request()->header('user-agent'); $agent = request()->header('user-agent');
$username = Users::where('email', $params['email'])->value('username'); app(LoginLog::class)->storeBy([
'login_name' => $params['login_name'],
Db::name('login_log')->insert([
'login_name' => $username ? : $params['email'],
'login_ip' => request()->ip(), 'login_ip' => request()->ip(),
'browser' => $this->getBrowser($agent), 'browser' => $this->getBrowser($agent),
'os' => $this->getOs($agent), 'os' => $this->getOs($agent),
'login_at' => time(), 'login_at' => time(),
'status' => $params['success'] ? 1 : 2, 'status' => $params['success'],
]); ]);
} }

View File

@@ -0,0 +1,30 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\login;
use catcher\ModuleService;
use think\Service;
class LoginService extends ModuleService
{
public function loadRouteFrom()
{
// TODO: Implement loadRouteFrom() method.
return __DIR__ . DIRECTORY_SEPARATOR . 'route.php';
}
public function loadEvents()
{
return [
'loginLog' => [ LoginLogEvent::class ],
];
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace catchAdmin\login\controller;
use catchAdmin\login\request\LoginRequest;
use catchAdmin\permissions\model\Users;
use catcher\base\CatchController;
use catcher\CatchAuth;
use catcher\CatchResponse;
use catcher\Code;
use catcher\exceptions\LoginFailedException;
use thans\jwt\facade\JWTAuth;
class Index extends CatchController
{
/**
* 登陆
*
* @time 2019年11月28日
* @param LoginRequest $request
* @param CatchAuth $auth
* @return bool|string
*/
public function login(LoginRequest $request, CatchAuth $auth)
{
$condition = $request->param();
try {
$token = $auth->attempt($condition);
$user = $auth->user();
$this->afterLoginSuccess($user, $token);
// 登录事件
$this->loginEvent($user->username);
return CatchResponse::success([
'token' => $token,
], '登录成功');
} catch (\Exception $exception) {
$this->detailWithLoginFailed($exception, $condition);
$code = $exception->getCode();
return CatchResponse::fail($code == Code::USER_FORBIDDEN ?
'该账户已被禁用,请联系管理员' : '登录失败,请检查邮箱和密码', Code::LOGIN_FAILED);
}
}
/**
* 处理登录失败
*
* @time 2020年10月26日
* @param $exception
* @param $condition
* @return void
*/
protected function detailWithLoginFailed($exception, $condition)
{
$message = $exception->getMessage();
if (strpos($message, '|') !== false) {
$username = explode('|', $message)[1];
} else {
$username = $condition['email'];
}
$this->loginEvent($username, false);
}
/**
* 用户登录成功后
*
* @time 2020年09月09日
* @param $user
* @param $token
* @return void
*/
protected function afterLoginSuccess($user, $token)
{
$user->last_login_ip = request()->ip();
$user->last_login_time = time();
if ($user->hasField('remember_token')) {
$user->remember_token = $token;
}
$user->save();
}
/**
* 登录事件
*
* @time 2020年09月09日
* @param $name
* @param bool $success
* @return void
*/
protected function loginEvent($name, $success = true)
{
$params['login_name'] = $name;
$params['success'] = $success ? 1 : 2;
event('loginLog', $params);
}
/**
* 登出
*
* @time 2019年11月28日
* @return \think\response\Json
*/
public function logout(): \think\response\Json
{
return CatchResponse::success();
}
/**
* refresh token
*
* @author JaguarJack
* @email njphper@gmail.com
* @time 2020/5/18
* @return \think\response\Json
*/
public function refreshToken()
{
return CatchResponse::success([
'token' => JWTAuth::refresh()
]);
}
}

15
catch/login/module.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "登陆",
"alias": "login",
"description": "login 模块",
"version": "1.0.0",
"keywords": [],
"order": 100,
"services": [
"\\catchAdmin\\login\\LoginService"
],
"aliases": {},
"files": [],
"requires": [],
"enable": true
}

View File

@@ -5,13 +5,15 @@ use catcher\base\CatchRequest;
class LoginRequest extends CatchRequest class LoginRequest extends CatchRequest
{ {
protected $needCreatorId = false;
protected function rules(): array protected function rules(): array
{ {
// TODO: Implement rules() method. // TODO: Implement rules() method.
return [ return [
'email|用户名' => 'email', 'email|用户名' => 'email',
'password|密码' => 'require', 'password|密码' => 'require',
'captcha|验证码' => 'require|captcha' // 'captcha|验证码' => 'require|captcha'
]; ];
} }
@@ -19,5 +21,6 @@ class LoginRequest extends CatchRequest
{ {
// TODO: Implement message() method. // TODO: Implement message() method.
return []; return [];
} }
} }

9
catch/login/route.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
$router->group(function () use ($router){
# 登入
$router->post('login', '\catchAdmin\login\controller\Index@login');
$router->post('logout', '\catchAdmin\login\controller\Index@logout');
$router->post('refresh/token', '\catchAdmin\login\controller\Index@refreshToken');
});

View File

@@ -0,0 +1,34 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor;
use catcher\ModuleService;
class MonitorService extends ModuleService
{
protected function loadConfig()
{
return require __DIR__ . DIRECTORY_SEPARATOR . 'config.php';
}
public function loadRouteFrom()
{
// TODO: Implement loadRouteFrom() method.
return __DIR__ . DIRECTORY_SEPARATOR . 'route.php';
}
public function loadCommands()
{
return [__NAMESPACE__, __DIR__ . DIRECTORY_SEPARATOR . 'command'];
}
}

View File

@@ -0,0 +1,175 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace catchAdmin\monitor\command;
use catchAdmin\monitor\command\process\Master;
use catchAdmin\monitor\command\process\Process;
use catcher\facade\FileSystem;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\console\Table;
class CatchCrontabCommand extends Command
{
protected $pid;
protected function configure()
{
// 指令配置
$this->setName('catch:crontab')
->addArgument('action', Argument::OPTIONAL, '[start|reload|stop|restart]', 'start')
->addOption('daemon', '-d', Option::VALUE_NONE, 'daemon mode')
->addOption('pid', '-p', Option::VALUE_REQUIRED, 'you can send signal to the process of pid')
->addOption('static', '-s', Option::VALUE_REQUIRED, 'default static process number', 1)
->addOption('dynamic', '-dy', Option::VALUE_REQUIRED, 'default dynamic process number', 10)
->addOption('interval', '-i', Option::VALUE_REQUIRED, 'interval/seconds', 5)
->setDescription('start catch crontab schedule');
}
protected function execute(Input $input, Output $output)
{
if (!$input->hasOption('pid')) {
$this->pid = Master::getMasterPid();
} else {
$this->pid = $input->getOption('pid');
}
if (!extension_loaded('pcntl') || !extension_loaded('posix')) {
$output->error('you should install extension [pcntl && posix]');
} else {
$this->{$input->getArgument('action')}();
}
}
/**
* 进程启动
*
* @time 2020年09月14日
* @return void
*/
protected function start()
{
$worker = new Master();
$worker->staticNumber($this->input->getOption('static'))
->dynamic($this->input->getOption('dynamic'))
->interval($this->input->getOption('interval'))
->asDaemon($this->input->hasOption('daemon'))
->run();
}
/**
* 停止任务
*
* @time 2020年07月07日
* @return void
*/
protected function stop()
{
$retryTimes = 0;
if (Process::isAlive($this->pid)) {
$this->output->info('🔨 catch crontab is running.');
Process::kill($this->pid, SIGTERM);
// 睡眠 1 秒
$this->output->info('⌛️ killing catch crontab service, please waiting...');
sleep(1);
if (!Process::isAlive($this->pid)) {
$this->output->info('🎉 catch crontab stopped!');
} else {
while (true) {
Process::kill($this->pid, SIGKILL);
if (Process::isAlive($this->pid)) {
$retryTimes++;
$this->output->info('🔥 retry $retryTimes times');
usleep(500 * 1000);
if ($retryTimes >= 3) {
$this->output->info('💔 catch crontab is running, stop failed, please use [kill -9 {$this->pid}] to Stop it');
break;
}
} else {
$this->output->info('🎉 catch crontab stopped!');
break;
}
}
}
Master::exitMasterDo();
} else {
$this->output->error('🤔️ catch crontab is not running, Please Check it!');
}
$this->output->info('🎉 stop catch crontab successfully');
}
/**
* 重启任务
*
* @time 2020年07月07日
* @return void
*/
protected function reload()
{
Process::kill($this->pid, SIGUSR1);
}
/**
* 重启
*
* @time 2020年07月07日
* @return void
*/
protected function restart()
{
$this->stop();
$this->output->info('catch crontab restarting...');
usleep(500 * 1000);
$this->start();
}
/**
* status
*
* @time 2020年07月22日
* @return void
*/
protected function status()
{
if ($this->pid) {
if (Process::isAlive($this->pid)) {
Process::kill($this->pid, SIGUSR2);
usleep(100000);
$worker = new Master;
$table = new Table;
$table->setHeader(['PID', '名称', '内存', '处理任务', '开始时间', '运行时间', '状态'], Table::ALIGN_CENTER);
$table->setRows($worker->getWorkerStatus(), Table::ALIGN_CENTER);
$this->output->info($table->render());
} else {
$this->output->error('🤔️ catch crontab is not running, Please Check it!');
}
} else {
$this->output->error('🤔️ catch crontab is not running, Please Check it!');
}
}
}

View File

@@ -0,0 +1,127 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace catchAdmin\monitor\command;
use catchAdmin\monitor\command\process\Process;
use catchAdmin\monitor\model\Crontab;
use catchAdmin\monitor\model\CrontabLog;
use Cron\CronExpression;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Log;
class ScheduleCommand extends Command
{
protected $pid;
protected function configure()
{
// 指令配置
$this->setName('catch:schedule')
->setDescription('catch schedule');
}
protected function execute(Input $input, Output $output)
{
try {
foreach ($this->getExecuteAbleCommands() as $command) {
$process = new Process(function (Process $process) use ($command) {
$this->executeCommand($command);
$process->exit();
});
$process->start();
}
} catch (\Exception $e) {
Log::error('CatchSchedule Error:' . $e->getMessage());
}
}
/**
* 执行 command
*
* @time 2021年01月18日
* @param $command
* @return void
*/
protected function executeCommand($command)
{
$start = time();
$errorMessage = '';
try {
$this->getConsole()->call($command->task);
} catch (\Exception $e) {
$errorMessage = $e->getMessage();
}
$end = time();
// 插入 crontab 执行日志
CrontabLog::insert([
'crontab_id' => $command->id,
'used_time' => $end - $start,
'status' => $errorMessage ? CrontabLog::FAILED : CrontabLog::SUCCESS,
'error_message' => $errorMessage,
'created_at' => time(),
'updated_at' => time(),
]);
}
/**
* 获取可执行任务
*
* @time 2021年01月17日
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return array
*/
protected function getExecuteAbleCommands()
{
$executeAbleCommands = [];
Crontab::where('status', Crontab::ENABLE)
->where('tactics', '<>', Crontab::EXECUTE_FORBIDDEN)
->select()
->each(function ($command) use (&$executeAbleCommands){
if ($command->tactics == Crontab::EXECUTE_IMMEDIATELY) {
$executeAbleCommands[] = $command;
return true;
}
$can = date('Y-m-d H:i', CronExpression::factory(trim($command->cron))
->getNextRunDate(date('Y-m-d H:i:s'), 0, true)
->getTimestamp()) == date('Y-m-d H:i', time());
if ($can) {
// 如果任务只执行一次 之后禁用该任务
if ($command->tactics === Crontab::EXECUTE_ONCE) {
Crontab::where('id', $command->id)->update([
'status' => Crontab::DISABLE,
]);
}
$executeAbleCommands[] = $command;
}
return true;
});
return $executeAbleCommands;
}
}

View File

@@ -0,0 +1,145 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\command\process;
use catcher\base\CatchCronTask;
trait Attributes
{
/**
* 是否以守护进程方式运行
*
* @var bool
*/
protected $daemon = false;
/**
* 静态进程数量
*
* @var int
*/
protected $static;
/**
* 动态进程数量
*
* @var int
*/
protected $dynamic;
/**
* 定时器触发时间
*
* @var int
*/
protected $interval;
/**
* set name
*
* @var
*/
protected $name = 'catch-crontab';
/**
* @var string
*/
protected $crontabQueueName = 'catch-crontab-task';
/**
* 安全退出
*
* @var bool
*/
protected $exitSafely = false;
/**
* 设置守护进程
*
* @time 2020年07月21日
* @param bool $daemon
* @return $this
*/
public function asDaemon($daemon = false)
{
$this->daemon = $daemon;
return $this;
}
public function staticNumber($n)
{
$this->static = $n;
return $this;
}
/**
* 可扩容
*
* @time 2020年07月21日
* @param $n
* @return $this
*/
public function dynamic($n)
{
$this->dynamic = $n;
return $this;
}
/**
* 定时
*
* @time 2020年07月21日
* @param $n
* @return $this
*/
public function interval($n)
{
$this->interval = $n;
return $this;
}
/**
* 设置 name
*
* @time 2020年07月23日
* @param $name
* @return $this
*/
public function name($name)
{
$this->name = $name;
return $this;
}
/**
* 设置报告错误
*
* @time 2020年07月24日
* @return void
*/
public function displayErrors()
{
ini_set('display_errors', 1);
error_reporting(E_ALL & ~E_WARNING);
ini_set('display_startup_errors', 1);
ini_set('ignore_repeated_errors', 1);
}
}

View File

@@ -0,0 +1,361 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\command\process;
use Exception;
use catcher\facade\Filesystem;
use think\cache\driver\Redis;
use think\facade\Cache;
/**
*
* - 以后台形式工作 daemon
* - 分静态进程和动态扩容进程
* - 信号处理机制
* - 重启工作进程
* - 重启服务
* - 定时器 扩容工作进程
* - 关闭进程
* - 统计信息
* - 是否拉起进程,工作进程销毁后是否继续主进程保留
* - Fatal Error 处理
* - Exception 处理
* - 发生内存泄漏如何处理
* - 错误输出到哪里
* - 提供基础面板查看
* - Log 文件的记录
*
* @time 2020年07月29日
*/
class Master
{
use RegisterSignal, Attributes, Store, ParseTask;
/**
* 保存子进程 PID
*
* @var array
*/
protected $workerIds = [];
/**
* 开始时间
*
* @var
*/
public $start_at;
/**
* @var
*/
public $worker_start_at;
/**
* 保存当前工作进程的数量
*
* @var
*/
protected $allWorkersCount;
/**
* 保存当前重定向输出文件
*
* @var string
*/
protected static $stdout;
/**
* 任务对象
*
* @var
*/
protected $taskService;
/**
* 处理的任务数量
*
* @var int
*/
protected $dealNum = 0;
/**
* busy waiting
*
* @var
*/
protected $status = 'waiting';
/**
* @var
*/
protected $redis;
/**
* 启动
*
* @time 2020年07月21日
* @return void
*/
public function run()
{
try {
if ($this->daemon) {
Process::daemon();
}
if ($this->interval) {
Process::alarm($this->interval);
}
$this->init();
// 初始化进程池
$this->initWorkers();
// 设置进程名称
Process::setWorkerName($this->name . ' master');
// 注册信号
$this->registerSignal();
// 写入进程状态
$this->setWorkerStatus($this->name . ' master');
// 信号发送
while (true) {
Process::dispatch();
$pid = pcntl_waitpid(-1, $status, WNOHANG);
Process::dispatch();
if ($pid > 0) {
if (isset($this->workerIds[$pid])) {
unset($this->workerIds[$pid]);
$this->deleteWorkerStatusFile($pid);
$this->worker_start_at = time();
// 如果进程挂掉,正常退出码都是 0当然这里可以自己定义看 exit($status) 设置什么
// 真实的 exit code pcntl_wexitstatus 函数获取
// exit code > 0 都是由于异常导致的
$exitCode = pcntl_wexitstatus($status);
if (!in_array($exitCode, [255, 250])) {
$this->forkStatic();
}
}
// 如果静态工作进程全部退出,会发生 CPU 空转,所以这里需要 sleep 1
if (!count($this->workerIds)) {
// sleep(1);
self::exitMasterDo();
exit(0);
}
}
usleep(500 * 1000);
}
} catch (\Throwable $exception) {
// todo
echo sprintf('[%s]: ', date('Y-m-d H:i:s')) . $exception->getMessage();
}
}
/**
* 初始化
* @throws Exception
*/
protected function init()
{
$this->displayErrors();
$this->start_at = $this->worker_start_at = time();
// 记录 masterID
FileSystem::put(self::masterPidStorePath(), posix_getpid());
// 保存信息
$this->saveTaskInfo();
// 初始化进程数量
$this->allWorkersCount = $this->static;
// 显示UI
$this->display();
// 重定向
$this->dup();
}
/**
* 初始化进程池
*
* @time 2020年07月21日
* @return void
*/
protected function initWorkers()
{
$this->redis = $this->getRedisHandle();
for ($i = 0; $i < $this->static; $i++) {
$this->forkStatic();
}
}
/**
* fork 进程
*
* @time 2020年07月21日
* @return void
*/
protected function forkDynamic()
{
$process = new Process(function (Process $process) {
$redis = $this->getRedisHandle();
while($crontab = $redis->rpop($this->crontabQueueName)) {
$task = $this->getTaskObject(\json_decode($crontab, true));
$task->run();
}
$process->exit();
});
$process->start();
$this->workerIds[$process->pid] = true;
}
/**
* 静态进程
*
* @time 2020年07月21日
* @return void
*/
protected function forkStatic()
{
$process = new Process(function (Process $process) {
$process->initMemory();
$name = $this->name . ' worker';
$this->setWorkerStatus($name, $this->dealNum, $this->status);
Process::setWorkerName($name);
Process::signal(SIGUSR2, function ($signal) use ($name) {
$this->setWorkerStatus($name, $this->dealNum, $this->status);
});
// 该信号保证进程完成任务后安全退出
Process::signal(SIGTERM, function ($signal) {
$this->exitSafely = true;
});
while (true) {
/************** 任务 *********************/
$this->status = 'busying';
$this->setWorkerStatus($name, $this->dealNum, 'busying');
// 处理定时任务
while ($crontab = $this->redis->rpop($this->crontabQueueName)) {
$task = $this->getTaskObject(\json_decode($crontab, true));
$task->run();
if ($task->shouldExit()) {
$process->exit(250);
}
$this->dealNum += 1;
}
$this->status = 'waiting';
$this->setWorkerStatus($name, $this->dealNum, 'waiting');
/****************处理*********************/
// 暂停一秒 让出CPU调度
sleep(1);
// 信号调度
Process::dispatch();
// 是否需要安全退出 || 查看内存是否溢出
if ($this->exitSafely || $process->isMemoryOverflow()) {
$process->exit();
//exit(0);
}
}
});
$process->start();
$this->workerIds[$process->pid] = true;
}
/**
* 重定向文件流
*
* @time 2020年07月22日
* @return void
* @throws Exception
*/
protected function dup()
{
if (!$this->daemon) {
return;
}
global $stdout, $stderr;
// 关闭标准输入输出
fclose(STDOUT);
fclose(STDIN);
fclose(STDERR);
// 重定向输出&错误
$stdoutPath = self::$stdout ?: self::stdoutPath();
!file_exists($stdoutPath) && touch($stdoutPath);
// 等待 100 毫秒
usleep(100 * 1000);
$stdout = fopen($stdoutPath, 'a');
$stderr = fopen($stdoutPath, 'a');
return;
}
/**
* 输出
*
* @time 2020年07月21日
* @return string
*/
public function output()
{
$isShowCtrlC = $this->daemon ? '' : 'Ctrl+c to stop' . "\r\n";
$info = <<<EOT
---------------------------------------------------------------- 🚀
| _ _ _ _ |
| | | | | | | | | |
| ___ __ _| |_ ___| |__ ___ _ __ ___ _ __ | |_ __ _| |__ |
| / __/ _` | __/ __| '_ \ / __| '__/ _ \| '_ \| __/ _` | '_ \ |
| | (_| (_| | || (__| | | | | (__| | | (_) | | | | || (_| | |_) ||
| \___\__,_|\__\___|_| |_| \___|_| \___/|_| |_|\__\__,_|_.__/ |
| | |
|----------------------------------------------------------------|
$isShowCtrlC
EOT;
return file_put_contents(self::statusPath(), $info);
}
/**
* 显示
*
* @time 2020年07月22日
* @return false|int
*/
protected function display()
{
$this->output();
return fwrite(STDOUT, $this->renderStatus());
}
/**
* 获取 redis 句柄
*
* @time 2020年09月15日
* @return object|null
*/
protected function getRedisHandle()
{
return Cache::store('redis')->handler();
}
}

View File

@@ -0,0 +1,47 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\command\process;
use catcher\facade\FileSystem;
use think\exception\ClassNotFoundException;
use think\helper\Str;
trait ParseTask
{
/**
* 获取任务
*
* @time 2020年09月15日
* @param $crontab
* @return mixed
*/
protected function getTaskObject($crontab)
{
$class = $this->getTaskNamespace() . ucfirst(Str::camel($crontab['task']));
if (class_exists($class)) {
return app()->make($class)->setCrontab($crontab);
}
throw new ClassNotFoundException('Task '. $crontab['task'] . ' not found');
}
/**
* 获取任务命名空间
*
* @time 2020年09月15日
* @return mixed
*/
protected function getTaskNamespace()
{
return config('catch.crontab.task_namespace');
}
}

View File

@@ -0,0 +1,213 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\command\process;
use catcher\exceptions\FailedException;
class Process
{
/**
* 保存工作进程 PID
*
* @var
*/
public $pid;
/**
* 用户自定义方法
*
* @var callable
*/
protected $callable;
/**
* 申请最大内存 给出缓冲期
*
* @var string
*/
protected $initMemory = '256M';
/**
* 超过最大内存报警
*
* @var float|int
*/
protected $allowMaxMemory = 128 * 1024 * 1024;
public function __construct(callable $callable)
{
$this->callable = $callable;
}
/**
* 守护进程
*
* @time 2020年07月21日
* @return void
* @throws FailedException
*/
public static function daemon()
{
$pid = pcntl_fork();
if ($pid < 0) {
throw new FailedException('fork process failed');
}
// 退出父进程
if ($pid > 0) {
exit(0);
}
// 设置新的会话组
if (posix_setsid() < 0) {
exit(0);
}
chdir('/');
// 重置掩码 权限问题
umask(0);
}
/**
* 启动进程
*
* @time 2020年07月21日
* @return void
*/
public function start()
{
$pid = pcntl_fork();
if ($this->pid < 0) {
exit('fork failed');
}
if ($pid > 0) {
$this->pid = $pid;
} else {
call_user_func_array($this->callable, [$this]);
}
}
/**
* 信号
*
* @time 2020年07月21日
* @param $signal
* @param $callable
* @param $restartSysCalls
* @return void
*/
public static function signal($signal, $callable, $restartSysCalls = false)
{
pcntl_signal($signal, $callable, $restartSysCalls);
}
/**
* default 1 second
*
* @param $interval
* @return mixed
*/
public static function alarm($interval = 1)
{
return pcntl_alarm($interval);
}
/**
* linux 进程下设置进程名称
*
* @time 2020年07月21日
* @param $title
* @return void
*/
public static function setWorkerName($title)
{
if (strtolower(PHP_OS) === 'linux') {
cli_set_process_title($title);
}
}
/**
* 安全退出
*
* @time 2020年07月21日
* @param int $status
* @return void
*/
public function exit($status = 0)
{
exit($status);
}
/**
* kill
*
* @time 2020年07月22日
* @param $pid
* @param $signal
* @return bool
*/
public static function kill($pid, $signal)
{
return posix_kill($pid, $signal);
}
/**
*
* @time 2020年07月22日
* @return void
*/
public static function dispatch()
{
pcntl_signal_dispatch();
}
/**
* 是否存活
*
* @time 2020年07月22日
* @param $pid
* @return bool
*/
public static function isAlive($pid)
{
return posix_kill($pid, 0);
}
/**
* 初始化进程内存
*
* @time 2020年07月22日
* @param int $memory
* @return void
*/
public function initMemory($memory = 0)
{
if (ini_get('memory_limit') != $this->initMemory) {
// 这里申请一块稍微大的内存
ini_set('memory_limit', $memory ?: $this->initMemory);
}
}
/**
* 是否超过最大内存
*
* @time 2020年07月22日
* @return mixed
*/
public function isMemoryOverflow()
{
// 一旦超过了允许的内存 直接退出进程
return memory_get_usage() > $this->allowMaxMemory;
}
}

View File

@@ -0,0 +1,158 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\command\process;
use catchAdmin\monitor\model\Crontab;
use catcher\facade\FileSystem;
use Cron\CronExpression;
use EasyWeChat\Kernel\Messages\News;
use think\cache\driver\Redis;
trait RegisterSignal
{
public function registerSignal()
{
// 退出信号
$this->exit();
// 等待子进程退出
$this->waitWorkersExit();
// 动态扩容
$this->workerChecked();
// 重启进程
$this->reload();
// 统计信息
$this->showStatus();
}
/**
* 进程退出
*
* @time 2020年07月21日
* @return void
*/
protected function exit()
{
Process::signal(SIGTERM, function ($signal) {
foreach ($this->workerIds as $pid => $v) {
if (isset($this->workerIds[$pid])) {
unset($this->workerIds[$pid]);
}
Process::kill($pid, SIGTERM);
}
Process::kill(self::getMasterPid(), SIGKILL);
});
Process::signal(SIGINT, function ($signal) {
foreach ($this->workerIds as $pid => $v) {
if (isset($this->workerIds[$pid])) {
unset($this->workerIds[$pid]);
}
Process::kill($pid, SIGKILL);
}
Process::kill(self::getMasterPid(), SIGKILL);
});
}
/**
* 子进程退出
*
* @time 2020年07月21日
* @return void
*/
protected function waitWorkersExit()
{
Process::signal(SIGCHLD, function ($signal) {
});
}
/**
* 进程检测
*
* @time 2020年07月21日
* @return void
*/
protected function workerChecked()
{
Process::signal(SIGALRM, function ($signal) {
$process = new Process(function (Process $process) {
$crontabs = Crontab::where('status', Crontab::ENABLE)
->where('tactics', '<>', Crontab::EXECUTE_FORBIDDEN)
->select()->toArray();
// 任务
foreach ($crontabs as $crontab) {
$can = date('Y-m-d H:i', CronExpression::factory(trim($crontab['cron']))
->getNextRunDate(date('Y-m-d H:i:s'), 0 , true)
->getTimestamp()) == date('Y-m-d H:i', time());
if ($can) {
// 如果任务只执行一次 之后禁用该任务
if ($crontab['tactics'] === Crontab::EXECUTE_ONCE) {
Crontab::where('id', $crontab['id'])->update([
'status' => Crontab::DISABLE,
]);
}
$redis = $this->getRedisHandle();
$redis->lpush($this->crontabQueueName, json_encode([
'id' => $crontab['id'],
'task' => $crontab['task'],
]));
}
}
$process->exit();
});
$process->start();
Process::alarm($this->interval);
});
}
/**
* 重启
*
* @time 2020年07月21日
* @return void
*/
protected function reload()
{
Process::signal(SIGUSR1, function ($signal) {
$this->worker_start_at = 0;
foreach ($this->workerIds as $pid => $v) {
Process::kill($pid, SIGTERM);
}
}, false);
}
/**
* 预留信号
*
* @time 2020年07月21日
* @return void
*/
protected function showStatus()
{
Process::signal(SIGUSR2, function ($signal) {
$this->setWorkerStatus($this->name . ' master');
foreach ($this->workerIds as $pid => $v) {
Process::kill($pid, SIGUSR2);
}
});
}
}

View File

@@ -0,0 +1,243 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\command\process;
use catcher\facade\FileSystem;
trait Store
{
/**
* worker 根目录
*
* @time 2020年07月23日
* @return string
*/
public static function storeTaskPath()
{
$path = config('catch.crontab.store_path');
if (!Filesystem::exists($path)) {
FileSystem::makeDirectory($path, 0777, true);
}
return $path;
}
/**
* 保存信息备用
*
* @time 2020年07月29日
* @return void
*/
protected function saveTaskInfo()
{
FileSystem::put(self::storeTaskPath() . 'information.json', \json_encode([
'name' => $this->name,
'static' => $this->static,
'dynamic' => $this->dynamic,
'interval' => $this->interval,
], JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
}
/**
* worker master pid
*
* @time 2020年07月23日
* @return string
*/
public static function masterPidStorePath()
{
return self::storeTaskPath() . 'master.pid';
}
/**
* worker master status
*
* @time 2020年07月23日
* @return string
*/
public static function statusPath()
{
return self::storeTaskPath() . 'master.status';
}
/**
* worker status
*
* @time 2020年07月23日
* @param string $name
* @return string
*/
public static function workerStatusPath($name)
{
$path = self::storeTaskPath() . 'status/';
if (!FileSystem::exists($path)) {
FileSystem::makeDirectory($path, 0777, true);
}
return $path . $name . '.status';
}
/**
*
* @time 2020年07月23日
* @return string
*/
public static function getWorkerStatusPath()
{
return self::storeTaskPath() . 'status/';
}
/**
* worker log
*
* @time 2020年07月23日
* @return string
*/
public static function stdoutPath()
{
return self::storeTaskPath() . 'errors.log';
}
/**
* 获取 master pid
*
* @time 2020年07月21日
* @return false|string
*/
public static function getMasterPid()
{
$pidFile = config('catch.crontab.master_pid_file');
if (!FileSystem::exists($pidFile)) {
return 0;
}
return FileSystem::sharedGet($pidFile);
}
/**
* status
*
* @time 2020年07月21日
* @return false|string
*/
public function renderStatus()
{
return FileSystem::sharedGet(self::statusPath());
}
/**
* 运行时间
*
* @time 2020年07月23日
* @param $runtime
* @return string
*/
protected function getRunningTime($runtime)
{
$day = 3600 * 24;
if ($runtime > $day) {
$days = floor($runtime / $day);
return $days . '天:' . gmstrftime('%H:%M:%S', $runtime % $day);
} else {
return gmstrftime('%H:%M:%S', $runtime);
}
}
/**
* 获取工作进程
*
* @time 2020年07月23日
* @return mixed
*/
public function getWorkerStatus()
{
usleep(500 * 1000);
$files = FileSystem::glob(self::storeTaskPath() . 'status/*.status');
$workerStatus = [];
foreach ($files as $file) {
$workerStatus[] = explode("\t", FileSystem::sharedGet($file));
}
return $workerStatus;
}
/**
* 设置进程状态
*
* @time 2020年07月23日
* @param $name
* @param int $dealNum
* @param string $status
* @return void
*/
protected function setWorkerStatus($name, $dealNum = 0, $status = 'running')
{
$startAt = strpos($name, 'worker') ? $this->worker_start_at : $this->start_at;
if ($this->daemon) {
FileSystem::put($this->workerStatusPath($this->workerStatusFileName($name)), implode("\t", [
posix_getpid(),
$name,
floor(memory_get_usage() / 1024 / 1024) . 'M',
$dealNum,
date('Y-m-d H:i:s', $startAt),
$this->getRunningTime(time() - $startAt),
$status
]));
}
}
/**
* 进程名称
*
* @time 2020年09月15日
* @param $name
* @return string
*/
protected function workerStatusFileName($name)
{
return $name . '_' . posix_getpid();
}
/**
* 删除进程状态文件
*
* @time 2020年09月15日
* @param $pid
* @return void
*/
protected function deleteWorkerStatusFile($pid)
{
@unlink(self::workerStatusPath($this->name . ' worker_' . $pid));
}
/**
* 退出
*
* @time 2020年09月15日
* @return void
*/
public static function exitMasterDo()
{
@unlink(self::masterPidStorePath());
@unlink(self::statusPath());
Filesystem::deleteDirectory(self::getWorkerStatusPath());
}
}

59
catch/monitor/config.php Normal file
View File

@@ -0,0 +1,59 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
return [
/**
*
* 定时任务配置
*
*/
'crontab' => [
/**
* 存储目录
*/
'store_path' => runtime_path('catch/crontab'),
/**
* 主进程 pid 存储
*/
'master_pid_file' => runtime_path('catch/crontab') . 'master.pid',
/**
* 日志配置
*/
'log' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => runtime_path('catch/schedule'),
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 0,
// 使用JSON格式记录
'json' => false,
// 日志处理
'processor' => null,
// 关闭通道日志写入
'close' => false,
// 日志输出格式化
'format' => '[%s][%s] %s',
// 是否实时写入
'realtime_write' => false,
],
/**
* crontab 任务命名空间
*/
'task_namespace' => '\\app\\task\\',
],
];

View File

@@ -0,0 +1,105 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\controller;
use catcher\base\CatchRequest as Request;
use catcher\CatchResponse;
use catcher\base\CatchController;
use catchAdmin\monitor\model\Crontab as CrontabModel;
use Cron\CronExpression;
class Crontab extends CatchController
{
protected $model;
public function __construct(CrontabModel $model)
{
$this->model = $model;
}
/**
* 列表
*
* @time 2020/09/14 20:35
*
* @return \think\Response
*/
public function index()
{
return CatchResponse::paginate($this->model->getList());
}
/**
* 保存
*
* @time 2020/09/14 20:35
* @param Request Request
* @return \think\Response
*/
public function save(Request $request)
{
CronExpression::factory($request->post('cron'));
return CatchResponse::success($this->model->storeBy($request->post()));
}
/**
* 读取
*
* @time 2020/09/14 20:35
* @param $id
* @return \think\Response
*/
public function read($id)
{
return CatchResponse::success($this->model->findBy($id));
}
/**
* 更新
*
* @time 2020/09/14 20:35
* @param Request $request
* @return \think\Response
*/
public function update(Request $request, $id)
{
CronExpression::factory($request->post('cron'));
return CatchResponse::success($this->model->updateBy($id, $request->post()));
}
/**
* 删除
*
* @time 2020/09/14 20:35
* @param $id
* @return \think\Response
*/
public function delete($id)
{
return CatchResponse::success($this->model->deleteBy($id));
}
/**
* 禁用启用
*
* @time 2020年09月15日
* @param $id
* @return \think\response\Json
*/
public function disOrEnable($id)
{
return CatchResponse::success($this->model->disOrEnable($id));
}
}

View File

@@ -0,0 +1,50 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\controller;
use catchAdmin\monitor\model\CrontabLog as LogModel;
use catcher\base\CatchController;
use catcher\CatchResponse;
use think\Request;
class CrontabLog extends CatchController
{
protected $model;
public function __construct(LogModel $model)
{
$this->model = $model;
}
/**
* 日志列表
*
* @time 2020年09月15日
* @throws \think\db\exception\DbException
* @return \think\response\Json
*/
public function index()
{
return CatchResponse::paginate($this->model->getList());
}
/**
* 删除日志
*
* @time 2020年09月15日
* @param $id
* @return \think\response\Json
*/
public function delete($id)
{
return CatchResponse::success($this->model->deleteBy($id));
}
}

View File

@@ -0,0 +1,46 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
use Phinx\Db\Adapter\MysqlAdapter;
class Crontab extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('crontab', ['engine' => 'InnoDB', 'collation' => 'utf8mb4_general_ci', 'comment' => '定时任务' ,'id' => 'id','signed' => true ,'primary_key' => ['id']]);
$table->addColumn('name', 'string', ['limit' => 255,'null' => false,'default' => '','signed' => false,'comment' => '任务名称',])
->addColumn('group', 'boolean', ['null' => false,'default' => 1,'signed' => false,'comment' => '1 默认 2 系统',])
->addColumn('task', 'string', ['limit' => 255,'null' => false,'default' => '','signed' => false,'comment' => '任务名称',])
->addColumn('cron', 'string', ['limit' => 50,'null' => false,'default' => '','signed' => false,'comment' => 'cron 表达式',])
->addColumn('tactics', 'boolean', ['null' => false,'default' => 1,'signed' => false,'comment' => '1 立即执行 2 执行一次 3 放弃执行',])
->addColumn('status', 'boolean', ['null' => false,'default' => 1,'signed' => false,'comment' => '1 正常 2 禁用',])
->addColumn('remark', 'string', ['limit' => 1000,'null' => false,'default' => '','signed' => false,'comment' => '备注',])
->addColumn('creator_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '创建人ID',])
->addColumn('created_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '创建时间',])
->addColumn('updated_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '更新时间',])
->addColumn('deleted_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '软删除',])
->create();
}
}

View File

@@ -0,0 +1,51 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
use think\migration\Migrator;
use think\migration\db\Column;
use Phinx\Db\Adapter\MysqlAdapter;
class CrontabLog extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('crontab_log', ['engine' => 'Myisam', 'collation' => 'utf8mb4_general_ci', 'comment' => '定时任务日志' ,'id' => 'id','signed' => true ,'primary_key' => ['id']]);
$table->addColumn('crontab_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => 'crontab 任务ID',])
->addColumn('used_time', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '任务消耗时间',])
->addColumn('status', 'boolean', ['null' => false,'default' => 1,'signed' => false,'comment' => '1 成功 2 失败',])
->addColumn('error_message', 'string', ['limit' => 1000,'null' => false,'default' => '','signed' => false,'comment' => '错误信息',])
->addColumn('created_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '创建时间',])
->addColumn('updated_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '更新时间',])
->addColumn('deleted_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '软删除',])
->create();
}
}

View File

@@ -0,0 +1,253 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
use think\migration\Seeder;
class MonitorMenusSeed extends Seeder
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* http://docs.phinx.org/en/latest/seeding.html
*/
public function run()
{
\catcher\Utils::importTreeData($this->getPermissions(), 'permissions', 'parent_id');
}
protected function getPermissions()
{
return array (
0 =>
array (
'id' => 103,
'permission_name' => '系统监控',
'parent_id' => 0,
'level' => '',
'route' => '/monitor',
'icon' => 'el-icon-view',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'monitor',
'component' => 'layout',
'redirect' => '/monitor/crontab',
'keepalive' => 1,
'type' => 1,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600126383,
'updated_at' => 1600136975,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 104,
'permission_name' => '定时任务',
'parent_id' => 103,
'level' => '103',
'route' => '/monitor/crontab',
'icon' => 'el-icon-time',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'crontab',
'component' => 'crontab',
'redirect' => '',
'keepalive' => 1,
'type' => 1,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600126931,
'updated_at' => 1600136975,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 105,
'permission_name' => '列表',
'parent_id' => 104,
'level' => '103-104',
'route' => '',
'icon' => '',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'crontab@index',
'component' => '',
'redirect' => '',
'keepalive' => 1,
'type' => 2,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600127069,
'updated_at' => 1600136975,
'deleted_at' => 0,
),
1 =>
array (
'id' => 106,
'permission_name' => '保存',
'parent_id' => 104,
'level' => '103-104',
'route' => '',
'icon' => '',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'crontab@save',
'component' => '',
'redirect' => '',
'keepalive' => 1,
'type' => 2,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600127078,
'updated_at' => 1600136975,
'deleted_at' => 0,
),
2 =>
array (
'id' => 107,
'permission_name' => '更新',
'parent_id' => 104,
'level' => '103-104',
'route' => '',
'icon' => '',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'crontab@update',
'component' => '',
'redirect' => '',
'keepalive' => 1,
'type' => 2,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600127085,
'updated_at' => 1600136975,
'deleted_at' => 0,
),
3 =>
array (
'id' => 108,
'permission_name' => '删除',
'parent_id' => 104,
'level' => '103-104',
'route' => '',
'icon' => '',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'crontab@delete',
'component' => '',
'redirect' => '',
'keepalive' => 1,
'type' => 2,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600127091,
'updated_at' => 1600136975,
'deleted_at' => 0,
),
4 =>
array (
'id' => 109,
'permission_name' => '禁用/启用',
'parent_id' => 104,
'level' => '103-104',
'route' => '',
'icon' => '',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'crontab@disOrEnable',
'component' => '',
'redirect' => '',
'keepalive' => 1,
'type' => 2,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600129279,
'updated_at' => 1600136975,
'deleted_at' => 0,
),
),
),
1 =>
array (
'id' => 110,
'permission_name' => '任务日志',
'parent_id' => 103,
'level' => '103-104',
'route' => '/monitor/crontab/log/:crontab_id?',
'icon' => 'el-icon-guide',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'CrontabLog',
'component' => 'crontabLog',
'redirect' => '',
'keepalive' => 1,
'type' => 1,
'hidden' => 2,
'sort' => 1,
'created_at' => 1600167562,
'updated_at' => 1600188651,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 111,
'permission_name' => '列表',
'parent_id' => 110,
'level' => '103-104-110',
'route' => '',
'icon' => '',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'CrontabLog@index',
'component' => '',
'redirect' => '',
'keepalive' => 1,
'type' => 2,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600167574,
'updated_at' => 1600168082,
'deleted_at' => 0,
),
1 =>
array (
'id' => 112,
'permission_name' => '删除',
'parent_id' => 110,
'level' => '103-104-110',
'route' => '',
'icon' => '',
'module' => 'monitor',
'creator_id' => 1,
'permission_mark' => 'CrontabLog@delete',
'component' => '',
'redirect' => '',
'keepalive' => 1,
'type' => 2,
'hidden' => 1,
'sort' => 1,
'created_at' => 1600167581,
'updated_at' => 1600168082,
'deleted_at' => 0,
),
),
),
),
),
);
}
}

View File

@@ -0,0 +1,43 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\model;
use catchAdmin\monitor\model\search\CrontabSearch;
use catcher\base\CatchModel as Model;
class Crontab extends Model
{
use CrontabSearch;
protected $name = 'crontab';
protected $field = [
'id', //
'name', // 任务名称
'group', // 1 默认 2 系统
'task', // 任务名称
'cron', // cron 表达式
'tactics', // 1 立即执行 2 执行一次 3 放弃执行
'status', // 1 正常 2 禁用
'remark', // 备注
'creator_id', // 创建人ID
'created_at', // 创建时间
'updated_at', // 更新时间
'deleted_at', // 软删除
];
const EXECUTE_IMMEDIATELY = 1; // 立即执行
const EXECUTE_ONCE = 2; // 执行一次
const EXECUTE_FORBIDDEN = 3; // 停止执行
}

View File

@@ -0,0 +1,53 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\model;
use catchAdmin\monitor\model\search\CrontabLogSearch;
use catcher\base\CatchModel;
class CrontabLog extends CatchModel
{
use CrontabLogSearch;
protected $name = 'crontab_log';
protected $field = [
'id', //
'crontab_id', // crontab 任务ID
'used_time', // 任务消耗时间
'status', // 1 成功 2 失败
'error_message', // 错误信息
'created_at', // 创建时间
'updated_at', // 更新时间
'deleted_at', // 软删除
];
const SUCCESS = 1;
const FAILED = 2;
/**
* 获取日志列表
*
* @time 2020年09月15日
* @throws \think\db\exception\DbException
* @return mixed|\think\Paginator
*/
public function getList()
{
return $this->catchLeftJoin(Crontab::class, 'id', 'crontab_id', ['name', 'group', 'task'])
->catchSearch()
->catchOrder()
->field(['used_time', 'error_message', 'crontab_log.status', 'crontab_log.id', 'crontab_log.created_at'])
->paginate();
}
}

View File

@@ -0,0 +1,39 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\model\search;
trait CrontabLogSearch
{
public function searchCrontabIdAttr($query, $value, $data)
{
return $query->where('crontab_id', $value);
}
public function searchNameAttr($query, $value, $data)
{
return $query->whereLike('crontab.name', $value);
}
public function searchStatusAttr($query, $value, $data)
{
return $query->where('crontab_log.status', $value);
}
public function searchStartAtAttr($query, $value, $data)
{
return $query->where($this->aliasField('created_at'), '>=', strtotime($value));
}
public function searchEndAtAttr($query, $value, $data)
{
return $query->where($this->aliasField('created_at'), '<=', strtotime($value));
}
}

View File

@@ -0,0 +1,24 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\monitor\model\search;
trait CrontabSearch
{
public function searchNameAttr($query, $value, $data)
{
return $query->whereLike('name', $value);
}
public function searchStatusAttr($query, $value, $data)
{
return $query->where('status', $value);
}
}

15
catch/monitor/module.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "系统监控",
"alias": "monitor",
"description": "系统监控模块",
"version": "1.0.0",
"keywords": [],
"order": 0,
"services": [
"\\catchAdmin\\monitor\\MonitorService"
],
"aliases": [],
"files": [],
"requires": [],
"enable": true
}

22
catch/monitor/route.php Normal file
View File

@@ -0,0 +1,22 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
// you should use `$router`
$router->group('monitor', function () use ($router){
// crontab路由
$router->resource('crontab', '\catchAdmin\monitor\controller\Crontab');
$router->put('crontab/enable/<id>', '\catchAdmin\monitor\controller\Crontab@disOrEnable');
// crontab 日志
$router->get('crontab/log/list', '\catchAdmin\monitor\controller\CrontabLog@index');
$router->delete('crontab/log/list/<id>', '\catchAdmin\monitor\controller\CrontabLog@delete');
})->middleware('auth');

View File

@@ -0,0 +1,54 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\permissions;
use catchAdmin\permissions\event\OperateLogEvent;
use catchAdmin\permissions\middleware\AuthTokenMiddleware;
use catchAdmin\permissions\middleware\PermissionsMiddleware;
use catchAdmin\permissions\middleware\RecordOperateMiddleware;
use catcher\ModuleService;
class PermissionService extends ModuleService
{
public function register()
{
parent::register(); // TODO: Change the autogenerated stub
$this->registerMiddleWares();
}
public function loadEvents()
{
return [
'operateLog' => [ OperateLogEvent::class ],
];
}
public function loadRouteFrom()
{
// TODO: Implement loadRouteFrom() method.
return __DIR__ . DIRECTORY_SEPARATOR . 'route.php';
}
protected function registerMiddleWares()
{
$middleware = $this->app->config->get('middleware');
$middleware['alias']['auth'] = [
AuthTokenMiddleware::class,
PermissionsMiddleware::class,
RecordOperateMiddleware::class
];
$this->app->config->set($middleware, 'middleware');
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace catchAdmin\permissions\controller;
use catcher\base\CatchController;
use catchAdmin\permissions\model\Department as DepartmentModel;
use catcher\base\CatchRequest;
use catcher\CatchResponse;
use catcher\exceptions\FailedException;
use catcher\Tree;
class Department extends CatchController
{
protected $department;
public function __construct(DepartmentModel $department)
{
$this->department = $department;
}
/**
* 列表
*
* @time 2020年01月09日
* @param CatchRequest $request
* @return \think\response\Json
* @throws \think\db\exception\DbException
*/
public function index(): \think\response\Json
{
return CatchResponse::success($this->department->getList());
}
/**
* 保存
*
* @time 2020年01月09日
* @param CatchRequest $request
* @return \think\response\Json
*/
public function save(CatchRequest $request): \think\response\Json
{
return CatchResponse::success($this->department->storeBy($request->param()));
}
/**
* 更新
*
* @time 2020年01月09日
* @param $id
* @param CatchRequest $request
* @return \think\response\Json
*/
public function update($id, CatchRequest $request): \think\response\Json
{
return CatchResponse::success($this->department->updateBy($id, $request->param()));
}
/**
* 删除
*
* @time 2020年01月09日
* @param $id
* @return \think\response\Json
*/
public function delete($id): \think\response\Json
{
if ($this->department->where('parent_id', $id)->find()) {
throw new FailedException('存在子部门,无法删除');
}
return CatchResponse::success($this->department->deleteBy($id));
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace catchAdmin\permissions\controller;
use catchAdmin\permissions\model\Job as JobModel;
use catcher\base\CatchController;
use catcher\base\CatchRequest;
use catcher\CatchResponse;
class Job extends CatchController
{
protected $job;
public function __construct(JobModel $job)
{
$this->job = $job;
}
/**
* 列表
*
* @time 2020年01月09日
* @param CatchRequest $request
* @return \think\response\Json
* @throws \think\db\exception\DbException
*/
public function index(): \think\response\Json
{
return CatchResponse::paginate($this->job->getList());
}
/**
* 保存
*
* @time 2020年01月09日
* @param CatchRequest $request
* @return \think\response\Json
*/
public function save(CatchRequest $request): \think\response\Json
{
return CatchResponse::success($this->job->storeBy($request->post()));
}
/**
* 更新
*
* @time 2020年01月09日
* @param $id
* @param CatchRequest $request
* @return \think\response\Json
*/
public function update($id, CatchRequest $request): \think\response\Json
{
return CatchResponse::success($this->job->updateBy($id, $request->post()));
}
/**
* 删除
*
* @time 2020年01月09日
* @param $id
* @return \think\response\Json
*/
public function delete($id): \think\response\Json
{
return CatchResponse::success($this->job->deleteBy($id));
}
/**
* 获取所有
*
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getAll()
{
return CatchResponse::success($this->job->field(['id', 'job_name'])->select());
}
}

View File

@@ -0,0 +1,208 @@
<?php
namespace catchAdmin\permissions\controller;
use catcher\base\CatchRequest as Request;
use catcher\base\CatchController;
use catcher\CatchResponse;
use catcher\exceptions\FailedException;
use catcher\library\ParseClass;
use catcher\Tree;
use catchAdmin\permissions\model\Permissions;
use think\helper\Str;
use think\response\Json;
class Permission extends CatchController
{
protected $permissions;
public function __construct(Permissions $permissions)
{
$this->permissions = $permissions;
}
/**
*
* @time 2019年12月11日
* @param Request $request
* @return Json
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
public function index(Request $request): Json
{
// 获取菜单类型
$menuList = $this->permissions->getList(true);
// 获取按钮类型并且重新排列
$buttonList = [];
$this->permissions
->whereIn('parent_id', array_unique($menuList->column('id')))
->where('type', Permissions::BTN_TYPE)
->select()->each(function ($item) use (&$buttonList){
$buttonList[$item['parent_id']][] = $item->toArray();
});
// 子节点的 key
$children = $request->param('actionList') ?? 'children';
// 返回树结构
return CatchResponse::success($menuList->each(function (&$item) use ($buttonList, $children){
$item[$children] = $buttonList[$item['id']] ?? [];
})->toTree());
}
/**
*
* @time 2019年12月11日
* @param Request $request
* @return Json
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
public function save(Request $request): Json
{
$params = $request->param();
// 如果是子分类 自动写入父类模块
$parentId = $params['parent_id'] ?? 0;
// 按钮类型寻找上级
if ($params['type'] == Permissions::BTN_TYPE && $parentId) {
$permissionMark = $params['permission_mark'];
// 查找父级
$parentPermission = $this->permissions->findBy($parentId);
// 如果父级是顶级 parent_id = 0
if ($parentPermission->parent_id) {
if (Str::contains($parentPermission->permission_mark, '@')) {
list($controller, $action) = explode('@', $parentPermission->permission_mark);
$permissionMark = $controller . '@' . $permissionMark;
} else {
$permissionMark = $parentPermission->permission_mark .'@'. $permissionMark;
}
}
$params['permission_mark'] = $permissionMark;
$params['module'] = $parentPermission->module;
}
return CatchResponse::success($this->permissions->storeBy($params));
}
/**
*
* @time 2019年12月11日
* @param $id
* @param Request $request
* @return Json
*/
public function update($id, Request $request): Json
{
$permission = $this->permissions->findBy($id);
$params = $request->param();
// 按钮类型
if ($params['type'] == Permissions::BTN_TYPE && $permission->parent_id) {
$parentPermission = $this->permissions->findBy($permission->parent_id);
$permissionMark = $params['permission_mark'];
if ($parentPermission->parent_id) {
if (Str::contains($parentPermission->permission_mark, '@')) {
list($controller, $action) = explode('@', $parentPermission->permission_mark);
$permissionMark = $controller . '@' . $permissionMark;
} else {
$permissionMark = $parentPermission->permission_mark .'@'. $permissionMark;
}
}
$params['permission_mark'] = $permissionMark;
$this->permissions->where('id',$id)->update(array_merge($params, [
'parent_id' => $permission->parent_id,
'level' => $permission->level,
'updated_at' => time()
]));
return CatchResponse::success();
}
$params = array_merge($request->param(), [
'parent_id' => $permission->parent_id,
'level' => $permission->level
]);
if ($permission->updateBy($id, $params)) {
if ($params['module'] ?? false) {
$this->permissions->updateBy($permission->id, [
'module' => $params['module'],
], 'parent_id');
}
return CatchResponse::success();
}
throw new FailedException('更新失败');
}
/**
*
* @time 2019年12月11日
* @param $id
* @throws FailedException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return Json
*/
public function delete($id): Json
{
if ($this->permissions->where('parent_id', $id)->find()) {
throw new FailedException('存在子菜单,无法删除');
}
$this->permissions->findBy($id)->roles()->detach();
return CatchResponse::success($this->permissions->deleteBy($id));
}
/**
* 显示/隐藏
*
* @author JaguarJack
* @email njphper@gmail.com
* @time 2020/5/19
* @param $id
* @return Json
*/
public function show($id)
{
$this->permissions->show($id);
return CatchResponse::success();
}
/**
*
* @time 2020年06月05日
* @param $id
* @param ParseClass $parseClass
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return Json
*/
public function getMethods($id, ParseClass $parseClass)
{
$permission = Permissions::where('id', $id)->find();
$module = $permission->module;
$controller = explode('@', $permission->permission_mark)[0];
try {
$methods = $parseClass->setModule('catch')->setRule($module, $controller)->onlySelfMethods();
return CatchResponse::success($methods);
}catch (\Exception $e) {
return CatchResponse::success([]);
}
}
}

View File

@@ -1,19 +1,21 @@
<?php <?php
namespace catchAdmin\permissions\controller; namespace catchAdmin\permissions\controller;
use app\Request; use catchAdmin\permissions\model\Permissions;
use catchAdmin\permissions\model\Roles;
use catcher\base\CatchRequest as Request;
use catcher\base\CatchController; use catcher\base\CatchController;
use catcher\CatchForm;
use catcher\CatchResponse; use catcher\CatchResponse;
use catcher\exceptions\FailedException; use catcher\exceptions\FailedException;
use catcher\Tree; use catcher\Tree;
use think\response\Json; use think\response\Json;
use catchAdmin\permissions\model\Roles as RoleModel;
class Role extends CatchController class Role extends CatchController
{ {
protected $role; protected $role;
public function __construct(\catchAdmin\permissions\model\Roles $role) public function __construct(RoleModel $role)
{ {
$this->role = $role; $this->role = $role;
} }
@@ -21,34 +23,11 @@ class Role extends CatchController
/** /**
* *
* @time 2019年12月09日 * @time 2019年12月09日
* @throws \Exception
* @return string * @return string
*/ */
public function index() public function index()
{ {
return $this->fetch(); return CatchResponse::success($this->role->getList());
}
/**
*
* @time 2019年12月11日
* @throws \Exception
* @return string
*/
public function create()
{
$form = new CatchForm();
$form->formId('role');
$form->text('role_name', '角色名称', true)->verify('required')->placeholder('请输入角色名称');
$form->hidden('parent_id')->default(\request()->param('id') ?? 0);
$form->textarea('description', '角色描述')->placeholder('请输入角色描述');
$form->dom('<div id="permissions"></div>', '权限');
$form->formBtn('submitRole');
return $this->fetch([
'form' => $form->render(),
'parent_id' => \request()->param('id') ?? 0,
]);
} }
/** /**
@@ -60,44 +39,27 @@ class Role extends CatchController
*/ */
public function save(Request $request) public function save(Request $request)
{ {
$this->role->storeBy($request->param()); $params = $request->param();
if (!empty($request->param('permissionids'))) { if (Roles::where('identify', $params['identify'])->find()) {
$this->role->attach($request->param('permissionids')); throw new FailedException('角色标识 [' . $params['identify'] . ']已存在');
} }
$this->role->storeBy($params);
$permissions = $params['permissions'];
if (!empty($permissions)) {
$this->role->attachPermissions(array_unique($permissions));
}
// 添加角色 // 添加角色
return CatchResponse::success(); return CatchResponse::success();
} }
public function read($id) public function read($id)
{
}
/**
*
* @time 2019年12月11日
* @param $id
* @throws \Exception
* @return string
*/
public function edit($id)
{ {
$role = $this->role->findBy($id); $role = $this->role->findBy($id);
$role->permissions = $role->getPermissions();
$form = new CatchForm(); return CatchResponse::success($role);
$form->formId('role');
$form->hidden('parent_id')->default($role->parent_id);
$form->text('role_name', '角色名称', true)->default($role->name)->verify('required')->placeholder('请输入角色名称');
$form->textarea('description', '角色描述')->default($role->description)->placeholder('请输入角色描述');
$form->dom('<div id="permissions"></div>', '权限');
$form->formBtn('submitRole');
return $this->fetch([
'form' => $form->render(),
'role_id' => $role->id,
'parent_id' => $role->parent_id
]);
} }
/** /**
@@ -108,16 +70,35 @@ class Role extends CatchController
* @return Json * @return Json
* @throws \think\db\exception\DbException * @throws \think\db\exception\DbException
*/ */
public function update($id, Request $request) public function update($id, Request $request): Json
{ {
$this->role->updateBy($id, $request->param()); if (Roles::where('identify', $request->param('identify'))->where('id', '<>', $id)->find()) {
throw new FailedException('角色标识 [' . $request->param('identify') . ']已存在');
}
$this->role->updateBy($id, $request->param());
$role = $this->role->findBy($id); $role = $this->role->findBy($id);
$role->detach(); $hasPermissionIds = $role->getPermissions()->column('id');
if (!empty($request->param('permissionids'))) { $permissionIds = $request->param('permissions');
$role->attach($request->param('permissionids'));
// 已存在权限 IDS
$existedPermissionIds = [];
foreach ($hasPermissionIds as $hasPermissionId) {
if (in_array($hasPermissionId, $permissionIds)) {
$existedPermissionIds[] = $hasPermissionId;
}
}
$attachIds = array_diff($permissionIds, $existedPermissionIds);
$detachIds = array_diff($hasPermissionIds, $existedPermissionIds);
if (!empty($detachIds)) {
$role->detachPermissions($detachIds);
}
if (!empty($attachIds)) {
$role->attachPermissions(array_unique($attachIds));
} }
return CatchResponse::success(); return CatchResponse::success();
@@ -133,14 +114,14 @@ class Role extends CatchController
* @throws \think\db\exception\ModelNotFoundException * @throws \think\db\exception\ModelNotFoundException
* @return Json * @return Json
*/ */
public function delete($id) public function delete($id): Json
{ {
if ($this->role->where('parent_id', $id)->find()) { if ($this->role->where('parent_id', $id)->find()) {
throw new FailedException('存在子角色,无法删除'); throw new FailedException('存在子角色,无法删除');
} }
$role = $this->role->findBy($id); $role = $this->role->findBy($id);
// 删除权限 // 删除权限
$role->detach(); $role->detachPermissions();
// 删除用户关联 // 删除用户关联
$role->users()->detach(); $role->users()->detach();
// 删除 // 删除
@@ -149,17 +130,6 @@ class Role extends CatchController
return CatchResponse::success(); return CatchResponse::success();
} }
/**
*
* @time 2019年12月11日
* @param Request $request
* @return Json
*/
public function list(Request $request)
{
return CatchResponse::success(Tree::done($this->role->getList($request->param())));
}
/** /**
* *
* @time 2019年12月11日 * @time 2019年12月11日
@@ -169,7 +139,7 @@ class Role extends CatchController
*/ */
public function getPermissions(Request $request, \catchAdmin\permissions\model\Permissions $permission): Json public function getPermissions(Request $request, \catchAdmin\permissions\model\Permissions $permission): Json
{ {
$parentRoleHasPermissionIds = null; $parentRoleHasPermissionIds = [];
if ($request->param('parent_id')) { if ($request->param('parent_id')) {
$permissions = $this->role->findBy($request->param('parent_id'))->getPermissions(); $permissions = $this->role->findBy($request->param('parent_id'))->getPermissions();
foreach ($permissions as $_permission) { foreach ($permissions as $_permission) {
@@ -177,9 +147,7 @@ class Role extends CatchController
} }
} }
$permissions = Tree::done($permission->getList([ $permissions = Tree::done(Permissions::whereIn('id', $parentRoleHasPermissionIds)->select()->toArray());
'permission_ids' => $parentRoleHasPermissionIds
]));
$permissionIds = []; $permissionIds = [];
if ($request->param('role_id')) { if ($request->param('role_id')) {

View File

@@ -0,0 +1,244 @@
<?php
namespace catchAdmin\permissions\controller;
use catchAdmin\permissions\excel\UserExport;
use catcher\base\CatchRequest as Request;
use catchAdmin\permissions\model\Permissions;
use catchAdmin\permissions\model\Roles;
use catchAdmin\permissions\model\Users;
use catchAdmin\permissions\request\CreateRequest;
use catchAdmin\permissions\request\UpdateRequest;
use catchAdmin\permissions\request\ProfileRequest;
use catcher\base\CatchController;
use catcher\CatchAuth;
use catcher\CatchCacheKeys;
use catcher\CatchResponse;
use catcher\library\excel\Excel;
use catcher\Tree;
use catcher\Utils;
use think\facade\Cache;
class User extends CatchController
{
protected $user;
public function __construct(Users $user)
{
$this->user = $user;
}
/**
*
* @time 2020年04月24日
* @throws \think\db\exception\DbException
* @return \think\response\Json
*/
public function index()
{
return CatchResponse::paginate($this->user->getList());
}
/**
* 获取用户信息
*
* @time 2020年01月07日
* @param CatchAuth $auth
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return \think\response\Json
*/
public function info(CatchAuth $auth)
{
$user = $auth->user();
$roles = $user->getRoles()->column('identify');
$permissionIds = $user->getPermissionsBy($user->id);
// 缓存用户权限
Cache::set(CatchCacheKeys::USER_PERMISSIONS . $user->id, $permissionIds);
$user->permissions = Permissions::getCurrentUserPermissions($permissionIds);
$user->roles = $roles;
// 用户数据权限
// $user->data_range = Roles::getDepartmentUserIdsBy($roles);
return CatchResponse::success($user);
}
/**
*
* @param CreateRequest $request
* @time 2019年12月06日
* @return \think\response\Json
*/
public function save(CreateRequest $request)
{
$this->user->storeBy($request->param());
$this->user->attachRoles($request->param('roles'));
if ($request->param('jobs')) {
$this->user->attachJobs($request->param('jobs'));
}
return CatchResponse::success('', '添加成功');
}
/**
*
* @time 2019年12月04日
* @param $id
* @return \think\response\Json
*/
public function read($id)
{
$user = $this->user->findBy($id);
$user->roles = $user->getRoles();
$user->jobs = $user->getJobs();
return CatchResponse::success($user);
}
/**
*
* @time 2019年12月04日
* @param $id
* @param UpdateRequest $request
* @return \think\response\Json
*/
public function update($id, UpdateRequest $request)
{
$this->user->updateBy($id, $request->filterEmptyField()->param());
$user = $this->user->findBy($id);
$user->detachRoles();
$user->detachJobs();
if (!empty($request->param('roles'))) {
$user->attachRoles($request->param('roles'));
}
if (!empty($request->param('jobs'))) {
$user->attachJobs($request->param('jobs'));
}
return CatchResponse::success();
}
/**
*
* @time 2019年12月04日
* @param $id
* @return \think\response\Json
*/
public function delete($id)
{
$ids = Utils::stringToArrayBy($id);
foreach ($ids as $_id) {
$user = $this->user->findBy($_id);
// 删除角色
$user->detachRoles();
// 删除岗位
$user->detachJobs();
$this->user->deleteBy($_id);
}
return CatchResponse::success();
}
/**
*
* @time 2019年12月07日
* @param $id
* @return \think\response\Json
*/
public function switchStatus($id): \think\response\Json
{
$ids = Utils::stringToArrayBy($id);
foreach ($ids as $_id) {
$user = $this->user->findBy($_id);
$this->user->updateBy($_id, [
'status' => $user->status == Users::ENABLE ? Users::DISABLE : Users::ENABLE,
]);
}
return CatchResponse::success([], '操作成功');
}
/**
*
* @time 2019年12月07日
* @param $id
* @return \think\response\Json
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
public function recover($id): \think\response\Json
{
$trashedUser = $this->user->findBy($id, ['*'], true);
if ($this->user->where('email', $trashedUser->email)->find()) {
return CatchResponse::fail(sprintf('该恢复用户的邮箱 [%s] 已被占用', $trashedUser->email));
}
return CatchResponse::success($this->user->recover($id));
}
/**
*
* @time 2019年12月11日
* @param Request $request
* @param Roles $roles
* @return \think\response\Json
*/
public function getRoles(Request $request, Roles $roles): \think\response\Json
{
$roles = Tree::done($roles->getList());
$roleIds = [];
if ($request->param('uid')) {
$userHasRoles = $this->user->findBy($request->param('uid'))->getRoles();
foreach ($userHasRoles as $role) {
$roleIds[] = $role->pivot->role_id;
}
}
return CatchResponse::success([
'roles' => $roles,
'hasRoles' => $roleIds,
]);
}
/**
* 导出
*
* @time 2020年09月08日
* @param Excel $excel
* @param UserExport $userExport
* @throws \PhpOffice\PhpSpreadsheet\Exception
* @return \think\response\Json
*/
public function export(Excel $excel, UserExport $userExport)
{
return CatchResponse::success($excel->save($userExport, Utils::publicPath('export/users')));
}
/**
* 更新个人信息
*
* @time 2020年09月20日
* @param ProfileRequest $request
* @return \think\response\Json
*/
public function profile(ProfileRequest $request)
{
return CatchResponse::success($this->user->updateBy($request->user()->id, $request->param()));
}
}

View File

@@ -32,8 +32,10 @@ class Users extends Migrator
$table->addColumn('username', 'string',array('limit' => 15,'default'=>'','comment'=>'用户名')) $table->addColumn('username', 'string',array('limit' => 15,'default'=>'','comment'=>'用户名'))
->addColumn('password', 'string',array('limit' => 255,'comment'=>'用户密码')) ->addColumn('password', 'string',array('limit' => 255,'comment'=>'用户密码'))
->addColumn('email', 'string',array('limit' => 100, 'comment'=>'邮箱 登录')) ->addColumn('email', 'string',array('limit' => 100, 'comment'=>'邮箱 登录'))
->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID'])
->addColumn('department_id', 'integer',['default' => 0, 'comment'=>'部门ID'])
->addColumn('status', 'boolean',array('limit' => 1,'default'=> 1,'comment'=>'用户状态 1 正常 2 禁用')) ->addColumn('status', 'boolean',array('limit' => 1,'default'=> 1,'comment'=>'用户状态 1 正常 2 禁用'))
->addColumn('last_login_ip', 'string',array('limit' => 30,'default'=>0,'comment'=>'最后登录IP')) ->addColumn('last_login_ip', 'string',array('limit' => 50,'default'=>0,'comment'=>'最后登录IP'))
->addColumn('last_login_time', 'integer',array('default'=>0,'comment'=>'最后登录时间', 'signed' => false)) ->addColumn('last_login_time', 'integer',array('default'=>0,'comment'=>'最后登录时间', 'signed' => false))
->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false )) ->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false ))
->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false)) ->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false))

View File

@@ -32,6 +32,8 @@ class Roles extends Migrator
$table->addColumn('role_name', 'string',['limit' => 15,'default'=>'','comment'=>'角色名']) $table->addColumn('role_name', 'string',['limit' => 15,'default'=>'','comment'=>'角色名'])
->addColumn('parent_id', 'integer',['default'=>0,'comment'=>'父级ID', 'signed' => false]) ->addColumn('parent_id', 'integer',['default'=>0,'comment'=>'父级ID', 'signed' => false])
->addColumn('description', 'string',['default'=> '','comment'=>'角色备注']) ->addColumn('description', 'string',['default'=> '','comment'=>'角色备注'])
->addColumn('data_range', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 0,'comment'=>'1 全部数据 2 自定义数据 3 仅本人数据 4 部门数据 5 部门及以下数据'])
->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID'])
->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false )) ->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false ))
->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false)) ->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false))
->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态0未删除 >0 已删除', 'signed' => false)) ->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态0未删除 >0 已删除', 'signed' => false))

View File

@@ -32,7 +32,9 @@ class Permissions extends Migrator
$table->addColumn('permission_name', 'string',['limit' => 15,'default'=>'','comment'=>'菜单名称']) $table->addColumn('permission_name', 'string',['limit' => 15,'default'=>'','comment'=>'菜单名称'])
->addColumn('parent_id', 'integer',['default'=>0,'comment'=>'父级ID', 'signed' => false]) ->addColumn('parent_id', 'integer',['default'=>0,'comment'=>'父级ID', 'signed' => false])
->addColumn('route', 'string', ['default' => '', 'comment' => '路由', 'limit' => 50]) ->addColumn('route', 'string', ['default' => '', 'comment' => '路由', 'limit' => 50])
->addColumn('icon', 'string', ['default' => '', 'comment' => '菜单图标', 'limit' => 50])
->addColumn('module', 'string', ['default' => '', 'comment' => '模块', 'limit' => 20]) ->addColumn('module', 'string', ['default' => '', 'comment' => '模块', 'limit' => 20])
->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID'])
->addColumn('method', 'string', ['default' => 'get', 'comment' => '路由请求方法', 'limit' => 15]) ->addColumn('method', 'string', ['default' => 'get', 'comment' => '路由请求方法', 'limit' => 15])
->addColumn('permission_mark', 'string', ['null' => false, 'comment' => '权限标识', 'limit' => 50]) ->addColumn('permission_mark', 'string', ['null' => false, 'comment' => '权限标识', 'limit' => 50])
->addColumn('type', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 菜单 2 按钮']) ->addColumn('type', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 菜单 2 按钮'])

View File

@@ -0,0 +1,45 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class Department extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('departments',['engine'=>'Innodb', 'comment' => '部门表', 'signed' => false]);
$table->addColumn('department_name', 'string',['limit' => 15,'default'=>'','comment'=>'部门名称'])
->addColumn('parent_id', 'integer',['default'=>0,'comment'=>'父级ID', 'signed' => false])
->addColumn('principal', 'string', ['default' => '', 'comment' => '负责人', 'limit' => 20])
->addColumn('mobile', 'string', ['default' => '', 'comment' => '联系电话', 'limit' => 20])
->addColumn('email', 'string', ['default' => '', 'comment' => '联系又想', 'limit' => 100])
->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID'])
->addColumn('status', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 正常 2 停用'])
->addColumn('sort', 'integer',['default'=> 0,'comment'=>'排序字段'])
->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false ))
->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false))
->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态null 未删除 timestamp 已删除', 'signed' => false))
->create();
}
}

View File

@@ -0,0 +1,43 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class Job extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('jobs',['engine'=>'Innodb', 'comment' => '岗位表', 'signed' => false]);
$table->addColumn('job_name', 'string',['limit' => 15,'default'=>'','comment'=>'岗位名称'])
->addColumn('coding', 'string', ['default' => '', 'comment' => '编码', 'limit' => 50])
->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID'])
->addColumn('status', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 正常 2 停用'])
->addColumn('sort', 'integer',['default'=> 0,'comment'=>'排序字段'])
->addColumn('description', 'string', ['default' => '', 'comment' => '描述', 'limit' => 255])
->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false ))
->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false))
->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态null 未删除 timestamp 已删除', 'signed' => false))
->create();
}
}

View File

@@ -0,0 +1,36 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class UserRelateJob extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('user_has_jobs',['engine'=>'Innodb', 'comment' => '用户角色表', 'signed' => false]);
$table->addColumn('uid', 'integer',['comment'=>'用户ID', 'signed' => false])
->addColumn('job_id', 'integer', ['comment'=>'岗位ID', 'signed' => false])
->create();
}
}

View File

@@ -0,0 +1,36 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class RoleHasDepartments extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('role_has_departments',['engine'=>'Innodb', 'comment' => '角色部门表', 'signed' => false]);
$table->addColumn('role_id', 'integer',['comment'=>'角色ID', 'signed' => false])
->addColumn('department_id', 'integer', ['comment'=>'部门ID', 'signed' => false])
->create();
}
}

View File

@@ -0,0 +1,41 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class ChangePermissions extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
if ($this->hasTable('permissions')) {
$table = $this->table('permissions');
$table->addColumn('component', 'string', ['default' => '', 'comment' => '组件名称', 'limit' => '255', 'after' => 'permission_mark'])
->addColumn('redirect', 'string', ['default' => '', 'comment' => '跳转地址', 'limit' => '255', 'after' => 'component'])
->addColumn('hide_children_in_menu', 'integer', ['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY, 'default' => 1, 'comment' => '1 显示 2隐藏', 'after' => 'redirect'])
->addColumn('keepalive', 'integer', ['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY, 'default' => 1, 'comment' => '1 缓存 2 不存在 ', 'after' => 'hide_children_in_menu'])
->update();
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class PermissionsAddColumn extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
if ($this->hasTable('permissions')) {
$table = $this->table('permissions');
$table->addColumn('level', 'string', ['default' => '', 'comment' => '层级', 'limit' => '50', 'after' => 'parent_id'])
->update();
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class AddPermissionStatusColumn extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
if ($this->hasTable('permissions')) {
$table = $this->table('permissions');
$table->addColumn('status', 'integer', [
'limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,
'default' => 1,
'comment' => '1 显示 2 隐藏',
'after' => 'type'])
->update();
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class UpdateRoles extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
if ($this->hasTable('roles')) {
$table = $this->table('roles');
$table->addColumn('identify', 'string', [
'limit' => 20,
'default' => 1,
'comment' => '角色的标识,用英文表示,用于后台路由权限',
'after' => 'role_name'])
->update();
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class UpdatePermissions extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
if ($this->hasTable('permissions')) {
$table = $this->table('permissions');
$table->removeColumn('method')
->removeColumn('hide_children_in_menu')
->renameColumn('status', 'hidden')
->update();
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
use think\migration\Migrator;
use think\migration\db\Column;
class AddUserAvatar extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
if ($this->hasTable('users')) {
$table = $this->table('users');
$table->addColumn('avatar', 'string', [
'limit' => 255,
'default' => '',
'comment' => '用户头像',
'after' => 'email'])
->update();
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
use think\migration\Migrator;
use think\migration\db\Column;
class AddUserRememberToken extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
if ($this->hasTable('users')) {
$table = $this->table('users');
$table->addColumn('remember_token', 'string', [
'limit' => 512,
'default' => '',
'comment' => '用户token',
'after' => 'avatar'])
->update();
}
}
}

View File

@@ -0,0 +1,39 @@
<?php
use think\migration\Seeder;
class DepartmentsSeed extends Seeder
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* http://docs.phinx.org/en/latest/seeding.html
*/
public function run()
{
$data = [
[
'id' => 1,
'department_name' => '总部',
'parent_id' => 0,
],
[
'id' => 2,
'department_name' => '北京总部',
'parent_id' => 1,
],
[
'id' => 3,
'department_name' => '南京总部',
'parent_id' => 1,
],
];
foreach ($data as $item) {
\catchAdmin\permissions\model\Department::create($item);
}
}
}

View File

@@ -0,0 +1,820 @@
<?php
use think\migration\Seeder;
class PermissionsMenusSeed extends Seeder
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* http://docs.phinx.org/en/latest/seeding.html
*/
public function run()
{
\catcher\Utils::importTreeData($this->getPermissions(), 'permissions', 'parent_id');
}
protected function getPermissions()
{
return array (
0 =>
array (
'id' => 1,
'permission_name' => '权限管理',
'parent_id' => 0,
'level' => '',
'route' => '/permissions',
'icon' => 'el-icon-cpu',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission',
'component' => 'layout',
'redirect' => '/permissions/users',
'hidden' => 1,
'keepalive' => 1,
'type' => 1,
'sort' => 100,
'created_at' => 1587461455,
'updated_at' => 1599362429,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 2,
'permission_name' => '用户管理',
'parent_id' => 1,
'level' => '1',
'route' => '/permissions/users',
'icon' => 'el-icon-user',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user',
'component' => 'users',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 1,
'sort' => 10,
'created_at' => 1587461597,
'updated_at' => 1599362429,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 3,
'permission_name' => '列表',
'parent_id' => 2,
'level' => '1-2',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user@index',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461647,
'updated_at' => 1599030266,
'deleted_at' => 0,
),
1 =>
array (
'id' => 4,
'permission_name' => '创建',
'parent_id' => 2,
'level' => '1-2',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user@create',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461696,
'updated_at' => 1599030266,
'deleted_at' => 0,
),
2 =>
array (
'id' => 5,
'permission_name' => '保存',
'parent_id' => 2,
'level' => '1-2',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user@save',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461721,
'updated_at' => 1599030266,
'deleted_at' => 0,
),
3 =>
array (
'id' => 6,
'permission_name' => '查看',
'parent_id' => 2,
'level' => '1-2',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user@edit',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461742,
'updated_at' => 1599030266,
'deleted_at' => 0,
),
4 =>
array (
'id' => 7,
'permission_name' => '更新',
'parent_id' => 2,
'level' => '1-2',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user@update',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461762,
'updated_at' => 1599030266,
'deleted_at' => 0,
),
5 =>
array (
'id' => 8,
'permission_name' => '删除',
'parent_id' => 2,
'level' => '1-2',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user@delete',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461841,
'updated_at' => 1599030266,
'deleted_at' => 0,
),
6 =>
array (
'id' => 9,
'permission_name' => '禁用',
'parent_id' => 2,
'level' => '1-2',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user@switchStatus',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461876,
'updated_at' => 1599030266,
'deleted_at' => 0,
),
7 =>
array (
'id' => 10,
'permission_name' => '恢复',
'parent_id' => 2,
'level' => '1-2',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'user@recover',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461901,
'updated_at' => 1599030266,
'deleted_at' => 0,
),
),
),
1 =>
array (
'id' => 11,
'permission_name' => '角色管理',
'parent_id' => 1,
'level' => '1',
'route' => '/permissions/roles',
'icon' => 'el-icon-s-custom',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'role',
'component' => 'roles',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 1,
'sort' => 9,
'created_at' => 1587461939,
'updated_at' => 1599362438,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 12,
'permission_name' => '列表',
'parent_id' => 11,
'level' => '1-11',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'role@index',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587461984,
'updated_at' => 1599362438,
'deleted_at' => 0,
),
1 =>
array (
'id' => 13,
'permission_name' => '创建',
'parent_id' => 11,
'level' => '1-11',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'role@create',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462007,
'updated_at' => 1599362438,
'deleted_at' => 0,
),
2 =>
array (
'id' => 14,
'permission_name' => '保存',
'parent_id' => 11,
'level' => '1-11',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'role@save',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462021,
'updated_at' => 1599362438,
'deleted_at' => 0,
),
3 =>
array (
'id' => 15,
'permission_name' => '查看',
'parent_id' => 11,
'level' => '1-11',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'role@edit',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462040,
'updated_at' => 1599362438,
'deleted_at' => 0,
),
4 =>
array (
'id' => 16,
'permission_name' => '更新',
'parent_id' => 11,
'level' => '1-11',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'role@update',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462058,
'updated_at' => 1599362438,
'deleted_at' => 0,
),
5 =>
array (
'id' => 17,
'permission_name' => '删除',
'parent_id' => 11,
'level' => '1-11',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'role@delete',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462070,
'updated_at' => 1599362438,
'deleted_at' => 0,
),
6 =>
array (
'id' => 18,
'permission_name' => '权限获取',
'parent_id' => 11,
'level' => '1-11',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'role@getPermissions',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462094,
'updated_at' => 1599362438,
'deleted_at' => 0,
),
),
),
2 =>
array (
'id' => 19,
'permission_name' => '菜单管理',
'parent_id' => 1,
'level' => '1',
'route' => '/permissions/rules',
'icon' => 'el-icon-collection-tag',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission',
'component' => 'rules',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 1,
'sort' => 8,
'created_at' => 1587462147,
'updated_at' => 1599362475,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 20,
'permission_name' => '列表',
'parent_id' => 19,
'level' => '1-19',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission@index',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462205,
'updated_at' => 1599362475,
'deleted_at' => 0,
),
1 =>
array (
'id' => 21,
'permission_name' => '创建',
'parent_id' => 19,
'level' => '1-19',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission@create',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462232,
'updated_at' => 1599362475,
'deleted_at' => 0,
),
2 =>
array (
'id' => 22,
'permission_name' => '保存',
'parent_id' => 19,
'level' => '1-19',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission@save',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462250,
'updated_at' => 1599362475,
'deleted_at' => 0,
),
3 =>
array (
'id' => 23,
'permission_name' => '禁用/启用',
'parent_id' => 19,
'level' => '1-19',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission@show',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462273,
'updated_at' => 1599362475,
'deleted_at' => 0,
),
4 =>
array (
'id' => 24,
'permission_name' => '更新',
'parent_id' => 19,
'level' => '1-19',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission@update',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462284,
'updated_at' => 1599362475,
'deleted_at' => 0,
),
5 =>
array (
'id' => 25,
'permission_name' => '删除',
'parent_id' => 19,
'level' => '1-19',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission@delete',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462296,
'updated_at' => 1599362475,
'deleted_at' => 0,
),
6 =>
array (
'id' => 106,
'permission_name' => '权限方法',
'parent_id' => 19,
'level' => '1-19',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'permission@getMethods',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1599221913,
'updated_at' => 1599362475,
'deleted_at' => 0,
),
),
),
3 =>
array (
'id' => 26,
'permission_name' => '部门管理',
'parent_id' => 1,
'level' => '1',
'route' => '/permissions/departments',
'icon' => 'el-icon-monitor',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'departments',
'component' => 'departments',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 1,
'sort' => 7,
'created_at' => 1587462488,
'updated_at' => 1599362429,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 27,
'permission_name' => '列表',
'parent_id' => 26,
'level' => '1-26',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'department@index',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462529,
'updated_at' => 1599030565,
'deleted_at' => 0,
),
1 =>
array (
'id' => 28,
'permission_name' => '保存',
'parent_id' => 26,
'level' => '1-26',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'department@save',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462548,
'updated_at' => 1599030565,
'deleted_at' => 0,
),
2 =>
array (
'id' => 29,
'permission_name' => '更新',
'parent_id' => 26,
'level' => '1-26',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'department@update',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462579,
'updated_at' => 1599030565,
'deleted_at' => 0,
),
3 =>
array (
'id' => 30,
'permission_name' => '删除',
'parent_id' => 26,
'level' => '1-26',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'department@delete',
'component' => '',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462592,
'updated_at' => 1599030565,
'deleted_at' => 0,
),
),
),
4 =>
array (
'id' => 31,
'permission_name' => '岗位管理',
'parent_id' => 1,
'level' => '1',
'route' => '/permissions/jobs',
'icon' => 'el-icon-setting',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'job',
'component' => 'jobs',
'redirect' => '',
'hidden' => 1,
'keepalive' => 1,
'type' => 1,
'sort' => 1,
'created_at' => 1587462707,
'updated_at' => 1599362429,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 32,
'permission_name' => '列表',
'parent_id' => 31,
'level' => '1-31',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'job@indexs',
'component' => '',
'redirect' => '',
'hidden' => 2,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462757,
'updated_at' => 1598959522,
'deleted_at' => 0,
),
1 =>
array (
'id' => 33,
'permission_name' => '保存',
'parent_id' => 31,
'level' => '1-31',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'job@save',
'component' => '',
'redirect' => '',
'hidden' => 2,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462774,
'updated_at' => 1598959522,
'deleted_at' => 0,
),
2 =>
array (
'id' => 34,
'permission_name' => '更新',
'parent_id' => 31,
'level' => '1-31',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'job@update',
'component' => '',
'redirect' => '',
'hidden' => 2,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462785,
'updated_at' => 1598959522,
'deleted_at' => 0,
),
3 =>
array (
'id' => 35,
'permission_name' => '删除',
'parent_id' => 31,
'level' => '1-31',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'job@delete',
'component' => '',
'redirect' => '',
'hidden' => 2,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462794,
'updated_at' => 1598959522,
'deleted_at' => 0,
),
4 =>
array (
'id' => 36,
'permission_name' => '获取全部',
'parent_id' => 31,
'level' => '1-31',
'route' => '',
'icon' => '',
'module' => 'permissions',
'creator_id' => 1,
'permission_mark' => 'job@getAll',
'component' => '',
'redirect' => '',
'hidden' => 2,
'keepalive' => 1,
'type' => 2,
'sort' => 1,
'created_at' => 1587462818,
'updated_at' => 1598959522,
'deleted_at' => 0,
),
),
),
),
),
);
}
}

View File

@@ -0,0 +1,38 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
use think\migration\Seeder;
class RolesSeed extends Seeder
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* http://docs.phinx.org/en/latest/seeding.html
*/
public function run()
{
\catchAdmin\permissions\model\Roles::create([
'role_name' => '超级管理员',
'identify' => 'admin',
'description' => 'super user',
'data_range' => 1,
'creator_id' => 1,
]);
\think\facade\Db::name( 'user_has_roles')->insert([
'role_id' => 1,
'uid' => 1,
]);
}
}

View File

@@ -14,10 +14,11 @@ class UsersSeed extends Seeder
*/ */
public function run() public function run()
{ {
return \catchAdmin\user\model\Users::create([ return \catchAdmin\permissions\model\Users::create([
'username' => 'admin', 'username' => 'admin',
'password' => 'admin', 'password' => 'catchadmin',
'email' => 'admin@gmail.com', 'email' => 'catch@admin.com',
'creator_id' => 1,
]); ]);
} }
} }

View File

@@ -0,0 +1,38 @@
<?php
namespace catchAdmin\permissions\event;
use catchAdmin\permissions\model\Permissions;
use catchAdmin\system\model\OperateLog;
use catcher\CatchAdmin;
use think\facade\Db;
class OperateLogEvent
{
public function handle($params)
{
$permission = $params['permission'];
$parentPermission = Permissions::where('id', $permission->parent_id)->value('permission_name');
$requestParams = request()->param();
// 如果参数过长则不记录
if (!empty($requestParams)) {
if (strlen(\json_encode($requestParams)) > 1000) {
$requestParams = [];
}
}
app(OperateLog::class)->storeBy([
'creator_id' => $params['creator_id'],
'module' => $parentPermission ? : '',
'method' => request()->method(),
'operate' => $permission->permission_name,
'route' => $permission->permission_mark,
'params' => !empty($requestParams) ? json_encode($requestParams, JSON_UNESCAPED_UNICODE) : '',
'created_at' => time(),
'ip' => request()->ip(),
]);
}
}

View File

@@ -0,0 +1,78 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\permissions\excel;
use catchAdmin\permissions\model\Users;
use catcher\library\excel\ExcelContract;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
class UserExport implements ExcelContract
{
/**
* 设置头部
*
* @time 2020年09月08日
* @return string[]
*/
public function headers(): array
{
// TODO: Implement headers() method.
return [
'id', '用户名', '邮箱', '状态', '创建日期'
];
}
/**
* 处理数据
*
* @time 2020年09月08日
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return \think\Collection
*/
public function sheets()
{
// TODO: Implement sheets() method.
$users = Users::field(['id', 'username', 'email', 'status', 'created_at'])->select();
foreach ($users as &$user) {
$user->status = $user->status == Users::ENABLE ? '启用' : '停用';
}
return $users;
}
/**
* 设置开始行
*
* @time 2020年09月08日
* @return int
*/
public function setRow()
{
return 2;
}
/**
* 设置标题
*
* @time 2020年09月08日
* @return array
*/
public function setTitle()
{
return [
'A1:G1', '导出用户', Alignment::HORIZONTAL_CENTER
];
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace catchAdmin\permissions\middleware;
use catcher\Code;
use catcher\exceptions\FailedException;
use thans\jwt\exception\TokenBlacklistException;
use thans\jwt\exception\TokenExpiredException;
use thans\jwt\exception\TokenInvalidException;
use thans\jwt\facade\JWTAuth;
use think\Middleware;
class AuthTokenMiddleware extends Middleware
{
public function handle($request, \Closure $next)
{
try {
JWTAuth::auth();
} catch (\Exception $e) {
if ($e instanceof TokenExpiredException) {
throw new FailedException('token 过期', Code::LOGIN_EXPIRED);
}
if ($e instanceof TokenBlacklistException) {
throw new FailedException('token 被加入黑名单', Code::LOGIN_BLACKLIST);
}
if ($e instanceof TokenInvalidException) {
throw new FailedException('token 不合法', Code::LOST_LOGIN);
}
throw new FailedException('登录用户不合法', Code::LOST_LOGIN);
}
return $next($request);
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace catchAdmin\permissions\middleware;
use app\Request;
use catchAdmin\permissions\model\Permissions;
use catcher\CatchCacheKeys;
use catcher\Code;
use catcher\exceptions\PermissionForbiddenException;
use think\facade\Cache;
use catcher\Utils;
class PermissionsMiddleware
{
/**
*
* @time 2019年12月12日
* @param Request $request
* @param \Closure $next
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws PermissionForbiddenException
*/
public function handle(Request $request, \Closure $next)
{
$rule = $request->rule()->getName();
if (!$rule) {
return $next($request);
}
// 模块忽略
[$module, $controller, $action] = Utils::parseRule($rule);
// toad
if (in_array($module, $this->ignoreModule())) {
return $next($request);
}
// 用户未登录
$user = $request->user();
if (!$user) {
throw new PermissionForbiddenException('Login is invalid', Code::LOST_LOGIN);
}
// 超级管理员
if (Utils::isSuperAdmin()) {
return $next($request);
}
// Get 请求
if ($this->allowGet($request)) {
return $next($request);
}
// 判断权限
$permission = property_exists($request, 'permission') ? $request->permission :
$this->getPermission($module, $controller, $action);
if (!$permission || !in_array($permission->id, Cache::get(CatchCacheKeys::USER_PERMISSIONS . $user->id))) {
throw new PermissionForbiddenException();
}
return $next($request);
}
/**
*
* @time 2019年12月14日
* @param $module
* @param $controllerName
* @param $action
* @param $request
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return array|bool|\think\Model|null
*/
protected function getPermission($module, $controllerName, $action)
{
$permissionMark = sprintf('%s@%s', $controllerName, $action);
return Permissions::where('module', $module)->where('permission_mark', $permissionMark)->find();
}
/**
* 忽略模块
*
* @time 2020年04月16日
* @return array
*/
protected function ignoreModule()
{
return ['login'];
}
/**
* 操作日志
*
* @time 2020年04月16日
* @param $creatorId
* @param $permission
* @return void
*/
protected function operateEvent($creatorId, $permission)
{
// 操作日志
$permission && event('operateLog', [
'creator_id' => $creatorId,
'permission' => $permission,
]);
}
/**
* get allow
*
* @time 2020年10月12日
* @param $request
* @return bool
* @throws \ReflectionException
*/
protected function allowGet($request)
{
if (Utils::isMethodNeedAuth($request->rule()->getName())) {
return false;
}
return $request->isGet() && config('catch.permissions.is_allow_get');
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace catchAdmin\permissions\middleware;
use app\Request;
use catchAdmin\permissions\model\Permissions;
use catcher\CatchCacheKeys;
use catcher\Code;
use catcher\exceptions\PermissionForbiddenException;
use think\facade\Cache;
use catcher\Utils;
class RecordOperateMiddleware
{
/**
*
* @time 2019年12月12日
* @param Request $request
* @param \Closure $next
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws PermissionForbiddenException
*/
public function handle(Request $request, \Closure $next)
{
$rule = $request->rule()->getName();
// 模块忽略
[$module, $controller, $action] = Utils::parseRule($rule);
$permission = $this->getPermission($module, $controller, $action);
$this->operateEvent($request->user()->id, $permission);
// 将权限带入
$request->permission = $permission;
return $next($request);
}
/**
*
* @time 2019年12月14日
* @param $module
* @param $controllerName
* @param $action
* @param $request
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return array|bool|\think\Model|null
*/
protected function getPermission($module, $controllerName, $action)
{
$permissionMark = sprintf('%s@%s', $controllerName, $action);
return Permissions::where('module', $module)->where('permission_mark', $permissionMark)->find();
}
/**
* 操作日志
*
* @time 2020年04月16日
* @param $creatorId
* @param $permission
* @return void
*/
protected function operateEvent($creatorId, $permission)
{
// 操作日志
$permission && event('operateLog', [
'creator_id' => $creatorId,
'permission' => $permission,
]);
}
}

View File

@@ -0,0 +1,96 @@
<?php
namespace catchAdmin\permissions\model;
use catcher\Utils;
trait DataRangScopeTrait
{
/**
* 数据范围查询
*
* @param $roles
* @return mixed
* @author JaguarJack <njphper@gmail.com>
* @date 2020/6/6
*/
public function dataRange($roles = [])
{
if (Utils::isSuperAdmin()) {
return $this;
}
$userIds = $this->getDepartmentUserIdsBy($roles);
if (empty($userIds)) {
return $this;
}
return $this->whereIn($this->aliasField('creator_id'), $userIds);
}
/**
* 获取部门IDs
*
* @param $roles
* @return array
* @author JaguarJack <njphper@gmail.com>
* @date 2020/6/6
*/
public function getDepartmentUserIdsBy($roles)
{
$userIds = [];
$isAll = false;
$user = request()->user();
if (empty($roles)) {
$roles = $user->getRoles();
}
foreach ($roles as $role) {
switch ($role->data_range) {
case Roles::ALL_DATA:
$isAll = true;
break;
case Roles::SELF_CHOOSE:
$departmentIds = array_merge(array_column($role->getDepartments()->toArray(), 'id'));
$userIds = array_merge($userIds, $this->getUserIdsByDepartmentId($departmentIds));
break;
case Roles::SELF_DATA:
$userIds[] = $user->id;
break;
case Roles::DEPARTMENT_DOWN_DATA:
// 查一下下级部门
$departmentIds = Department::where('parent_id', $user->department_id)->column('id');
$departmentIds[] = $user->department_id;
$userIds = array_merge([$user->id], $this->getUserIdsByDepartmentId($departmentIds));
break;
case Roles::DEPARTMENT_DATA:
$userIds = array_merge($userIds, $this->getUserIdsByDepartmentId([$user->department_id]));
break;
default:
break;
}
// 如果有全部数据 直接跳出
if ($isAll) {
break;
}
}
return $userIds;
}
/**
* 获取UserID
*
* @time 2020年07月04日
* @param $id
* @return array
*/
protected function getUserIdsByDepartmentId(array $id)
{
return Users::whereIn('department_id', $id)->column('id');
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace catchAdmin\permissions\model;
use catchAdmin\permissions\model\search\DepartmentSearch;
use catcher\base\CatchModel;
use think\db\exception\DbException;
class Department extends CatchModel
{
use DepartmentSearch;
protected $name = 'departments';
protected $field = [
'id', //
'department_name', // 部门名称
'parent_id', // 父级ID
'principal', // 负责人
'mobile', // 联系电话
'email', // 联系又想
'creator_id', // 创建人ID
'status', // 1 正常 2 停用
'sort', // 排序字段
'created_at', // 创建时间
'updated_at', // 更新时间
'deleted_at', // 删除状态null 未删除 timestamp 已删除
];
/**
* 列表数据
*
* @time 2020年01月09日
* @return array
* @throws DbException
*/
public function getList(): array
{
return $this->catchSearch()
->catchOrder()
->select()->toTree();
}
/**
* 获取子部门IDS
*
* @time 2020年11月04日
* @param $id
* @throws DbException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @return mixed
*/
public static function getChildrenDepartmentIds($id)
{
$departmentIds = Department::field(['id', 'parent_id'])->select()->getAllChildrenIds([$id]);
$departmentIds[] = $id;
return $departmentIds;
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace catchAdmin\permissions\model;
trait HasDepartmentsTrait
{
/**
*
* @time 2019年12月08日
* @return mixed
*/
public function departments()
{
return $this->belongsToMany(Department::class, 'role_has_departments', 'department_id', 'role_id');
}
/**
*
* @time 2019年12月08日
* @return mixed
*/
public function getDepartments()
{
return $this->departments()->select();
}
/**
*
* @time 2019年12月08日
* @param array $departments
* @return mixed
*/
public function attachDepartments(array $departments)
{
if (empty($departments)) {
return true;
}
sort($departments);
return $this->departments()->attach($departments);
}
/**
*
* @time 2019年12月08日
* @param array $departments
* @return mixed
*/
public function detachDepartments(array $departments = [])
{
if (empty($departments)) {
return $this->departments()->detach();
}
return $this->departments()->detach($departments);
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace catchAdmin\permissions\model;
trait HasJobsTrait
{
/**
*
* @time 2019年12月08日
* @return mixed
*/
public function jobs()
{
return $this->belongsToMany(Job::class, 'user_has_jobs', 'job_id', 'uid');
}
/**
*
* @time 2019年12月08日
* @param array $fields
* @return mixed
*/
public function getJobs()
{
return $this->jobs()->select();
}
/**
*
* @time 2019年12月08日
* @param array $jobs
* @return mixed
*/
public function attachJobs(array $jobs)
{
if (empty($jobs)) {
return true;
}
sort($jobs);
return $this->jobs()->attach($jobs);
}
/**
*
* @time 2019年12月08日
* @param array $jobs
* @return mixed
*/
public function detachJobs(array $jobs = [])
{
if (empty($jobs)) {
return $this->jobs()->detach();
}
return $this->jobs()->detach($jobs);
}
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* @filename HasPermissionsTrait.php
* @createdAt 2020/1/14
* @project https://github.com/yanwenwu/catch-admin
* @document http://doc.catchadmin.com
* @author JaguarJack <njphper@gmail.com>
* @copyright By CatchAdmin
* @license https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt
*/
namespace catchAdmin\permissions\model;
trait HasPermissionsTrait
{
/**
*
* @time 2019年12月09日
* @return \think\model\relation\BelongsToMany
*/
public function permissions(): \think\model\relation\BelongsToMany
{
return $this->belongsToMany(Permissions::class, 'role_has_permissions', 'permission_id', 'role_id');
}
/**
*
* @time 2019年12月08日
* @param array $condition
* @param array $field
* @return mixed
*/
public function getPermissions($condition = [], $field = [])
{
return $this->permissions()
->when(!empty($field), function ($query) use ($field){
$query->field($field);
})
->when(!empty($condition), function ($query) use ($condition){
$query->where($condition);
})
->select();
}
/**
*
* @time 2019年12月08日
* @param array $permissions
* @return mixed
* @throws \think\db\exception\DbException
*/
public function attachPermissions(array $permissions)
{
if (empty($permissions)) {
return true;
}
sort($permissions);
return $this->permissions()->attach($permissions);
}
/**
*
* @time 2019年12月08日
* @param array $permissions
* @return mixed
*/
public function detachPermissions(array $permissions = [])
{
if (empty($permissions)) {
return $this->permissions()->detach();
}
return $this->permissions()->detach($permissions);
}
}

View File

@@ -16,6 +16,7 @@ trait HasRolesTrait
/** /**
* *
* @time 2019年12月08日 * @time 2019年12月08日
* @param array $fields
* @return mixed * @return mixed
*/ */
public function getRoles() public function getRoles()
@@ -29,7 +30,7 @@ trait HasRolesTrait
* @param array $roles * @param array $roles
* @return mixed * @return mixed
*/ */
public function attach(array $roles) public function attachRoles(array $roles)
{ {
if (empty($roles)) { if (empty($roles)) {
return true; return true;
@@ -46,7 +47,7 @@ trait HasRolesTrait
* @param array $roles * @param array $roles
* @return mixed * @return mixed
*/ */
public function detach(array $roles = []) public function detachRoles(array $roles = [])
{ {
if (empty($roles)) { if (empty($roles)) {
return $this->roles()->detach(); return $this->roles()->detach();

View File

@@ -0,0 +1,39 @@
<?php
namespace catchAdmin\permissions\model;
use catchAdmin\permissions\model\search\JobsSearch;
use catcher\base\CatchModel;
class Job extends CatchModel
{
use JobsSearch;
protected $name = 'jobs';
protected $field = [
'id', //
'job_name', // 岗位名称
'coding', // 编码
'creator_id', // 创建人ID
'status', // 1 正常 2 停用
'sort', // 排序字段
'description', // 描述
'created_at', // 创建时间
'updated_at', // 更新时间
'deleted_at', // 删除状态null 未删除 timestamp 已删除
];
/**
* 列表
*
* @time 2020年01月09日
* @param $params
* @throws \think\db\exception\DbException
* @return \think\Paginator
*/
public function getList()
{
return $this->catchSearch()
->paginate();
}
}

View File

@@ -0,0 +1,142 @@
<?php
namespace catchAdmin\permissions\model;
use catchAdmin\permissions\model\search\PermissionsSearch;
use catcher\base\CatchModel;
use think\Model;
class Permissions extends CatchModel
{
use PermissionsSearch;
protected $name = 'permissions';
protected $field = [
'id', //
'permission_name', // 菜单名称
'parent_id', // 父级ID
'icon',
'component', // 组件
'redirect',
'keepalive',
'creator_id',
'hidden',
'module', // 模块
'route', // 路由
'permission_mark', // 权限标识
'type', // 1 菜单 2 按钮
'sort', // 排序字段
'created_at', // 创建时间
'updated_at', // 更新时间
'deleted_at', // 删除状态null 未删除 timestamp 已删除
];
public const MENU_TYPE = 1;
public const BTN_TYPE = 2;
public const GET = 'get';
public const POST = 'post';
public const PUT = 'put';
public const DELETE = 'delete';
public function getList($isMenu = false)
{
return $this->catchSearch()
->catchOrder()
->when($isMenu, function ($query){
$query->where('type', self::MENU_TYPE);
})
->select();
}
public function roles(): \think\model\relation\BelongsToMany
{
return $this->belongsToMany(Roles::class, 'role_has_permissions', 'role_id', 'permission_id');
}
/**
* 获取当前用户权限
*
* @time 2020年01月14日
* @param array $permissionIds
* @return \think\Collection
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
public static function getCurrentUserPermissions(array $permissionIds): \think\Collection
{
return parent::whereIn('id', $permissionIds)
->field(['permission_name as title', 'id', 'parent_id',
'route', 'icon', 'component', 'redirect', 'module',
'keepalive as keepAlive', 'type', 'permission_mark', 'hidden'
])
->catchOrder()
->select();
}
/**
* 插入后回调 更新 level
*
* @time 2020年04月22日
* @param Model $model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return array|bool|Model|void|null
*/
public static function onAfterInsert(Model $model)
{
$model = self::where('id', $model->id)->find();
if ($model && $model->parent_id) {
$parent = self::where('id', $model->parent_id)->find();
$level = $parent->level ? $parent->level . '-' . $parent->id : $parent->id;
return $model->where('id', $model->id)->update([
'level' => $level
]);
}
return true;
}
public function show($id)
{
$permission = $this->findBy($id);
// 不能使用改属性判断,模型有该属性,使用数组方式
// $permission->hidden
$hidden = $permission['hidden'] == Permissions::ENABLE ? Permissions::DISABLE : Permissions::ENABLE;
$nextLevelIds = $this->getNextLevel([$id]);
$nextLevelIds[] = $id;
return $this->whereIn('id', $nextLevelIds)->update([
'hidden' => $hidden,
'updated_at' => time(),
]);
}
/**
* 获取 level ids
*
* @time 2020年09月06日
* @param array $id
* @param array $ids
* @return array
*/
protected function getNextLevel(array $id, &$ids = [])
{
$_ids = $this->whereIn('parent_id', $id)
->where('type', self::MENU_TYPE)
->column('id');
if (count($_ids)) {
$ids = array_merge($_ids, $this->getNextLevel($_ids, $ids));
}
return $ids;
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace catchAdmin\permissions\model;
use catchAdmin\permissions\model\search\RolesSearch;
use catcher\base\CatchModel;
class Roles extends CatchModel
{
use HasDepartmentsTrait;
use HasPermissionsTrait;
use RolesSearch;
protected $name = 'roles';
public const ALL_DATA = 1; // 全部数据
public const SELF_CHOOSE = 2; // 自定义数据
public const SELF_DATA = 3; // 本人数据
public const DEPARTMENT_DATA = 4; // 部门数据
public const DEPARTMENT_DOWN_DATA = 5; // 部门及以下数据
protected $field = [
'id', //
'role_name', // 角色名
'identify', // 身份标识
'parent_id', // 父级ID
'creator_id', // 创建者
'data_range', // 数据范围
'description', // 角色备注
'created_at', // 创建时间
'updated_at', // 更新时间
'deleted_at', // 删除状态0未删除 >0 已删除
];
public function getList()
{
return $this->catchSearch()
->order('id', 'desc')
->select()
->toTree();
}
/**
*
* @time 2019年12月08日
* @return \think\model\relation\BelongsToMany
*/
public function users(): \think\model\relation\BelongsToMany
{
return $this->belongsToMany(Users::class, 'user_has_roles', 'uid', 'role_id');
}
}

View File

@@ -0,0 +1,111 @@
<?php
namespace catchAdmin\permissions\model;
use catchAdmin\permissions\model\search\UserSearch;
use catcher\base\CatchModel;
use catcher\exceptions\FailedException;
use catcher\Utils;
class Users extends CatchModel
{
use HasRolesTrait;
use HasJobsTrait;
use UserSearch;
protected $name = 'users';
protected $field = [
'id', //
'username', // 用户名
'password', // 用户密码
'email', // 邮箱 登录
'avatar', // 头像
'remember_token',
'creator_id', // 创建者ID
'department_id', // 部门ID
'status', // 用户状态 1 正常 2 禁用
'last_login_ip', // 最后登录IP
'last_login_time', // 最后登录时间
'created_at', // 创建时间
'updated_at', // 更新时间
'deleted_at', // 删除状态0未删除 >0 已删除
];
/**
* set password
*
* @time 2019年12月07日
* @param $value
* @return false|string
*/
public function setPasswordAttr($value)
{
return password_hash($value, PASSWORD_DEFAULT);
}
/**
* 用户列表
*
* @time 2019年12月08日
* @throws \think\db\exception\DbException
* @return \think\Paginator
*/
public function getList(): \think\Paginator
{
return $this->withoutField(['updated_at'], true)
->catchSearch()
->catchLeftJoin(Department::class, 'id', 'department_id', ['department_name'])
->order($this->aliasField('id'), 'desc')
->paginate();
}
/**
* 获取权限
*
* @time 2019年12月12日
* @param $uid
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return array
*/
public function getPermissionsBy($uid = 0): array
{
// 获取超级管理配置 超级管理员全部权限
if ($uid == config('catch.permissions.super_admin_id')) {
return Permissions::select()->column('id');
}
$roles = $uid ? $this->findBy($uid)->getRoles() : $this->getRoles();
$permissionIds = [];
foreach ($roles as $role) {
$permissionIds = array_merge($permissionIds, $role->getPermissions()->column('id'));
}
return array_unique($permissionIds);
}
/**
* 后台根据权限标识判断用户是否拥有某个权限
* @param string $permission_mark
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*
* 用法 request()->user()->can('permission@create');
*/
public function can($permission_mark)
{
// 超级管理员直接返回true
if (Utils::isSuperAdmin()){
return true;
}
// 查询当前用户的权限
return in_array(
Permissions::where('permission_mark',$permission_mark)->value('id') ? : 0,
$this->getPermissionsBy()
);
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace catchAdmin\permissions\model\search;
trait DepartmentSearch
{
public function searchDepartmentNameAttr($query, $value, $data)
{
return $query->whereLike('department_name', $value);
}
public function searchStatusAttr($query, $value, $data)
{
return $query->where('status', $value);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace catchAdmin\permissions\model\search;
trait JobsSearch
{
public function searchJobNameAttr($query, $value, $data)
{
return $query->whereLike('job_name', $value);
}
public function searchCodingAttr($query, $value, $data)
{
return $query->whereLike('coding', $value);
}
public function searchStatusAttr($query, $value, $data)
{
return $query->where('status', $value);
}
}

Some files were not shown because too many files have changed in this diff Show More