878 Commits
v1.0 ... v2.6.1

Author SHA1 Message Date
JaguarJack
fb579a5771 update:新增选择数据权限默认选项#gitee#issueI3NNH1 2021-04-24 20:35:33 +08:00
JaguarJack
4e1e040936 add:新增导入导出公共接口 2021-04-24 20:32:36 +08:00
JaguarJack
38e10896d4 update:新增模型导入方法 2021-04-24 20:32:05 +08:00
JaguarJack
ba1595f75f update:新增本地上传方法 2021-04-24 20:31:45 +08:00
JaguarJack
566514f729 delete:transtrait 2021-04-24 20:31:19 +08:00
JaguarJack
48c41f7948 add:新增excel的导入导出组件 2021-04-24 20:30:28 +08:00
JaguarJack
f67a4f33d5 add:新增导入组件 2021-04-24 20:29:33 +08:00
JaguarJack
ae53d4e404 add:新增菜单创建restful快捷方式 2021-04-20 18:56:05 +08:00
JaguarJack
504054b68e add:新增获取省市区数据命令 2021-04-20 08:46:14 +08:00
JaguarJack
ceb5a396d8 update:优化基础组件 2021-04-20 08:45:08 +08:00
JaguarJack
be91cfbc4f fixed#gitee#I3J1IL 2021-04-18 07:45:02 +08:00
JaguarJack
898ffbc822 update:更新Editor组件 2021-04-11 21:01:41 +08:00
JaguarJack
f321a71677 update:更新table&form组件 2021-04-10 21:57:51 +08:00
JaguarJack
246d2caf44 update:修改搜索label文字错误 2021-04-10 08:13:34 +08:00
JaguarJack
d020c99db3 fixed:权限菜单错误&用户修改密码 2021-04-09 08:07:22 +08:00
JaguarJack
44b74d53d9 update:更新一些页面操作 2021-04-05 22:11:36 +08:00
JaguarJack
4e170dbd17 add:新增强制更新组件方法 2021-04-05 22:03:25 +08:00
JaguarJack
f7c8d65ea9 update:更新搜索组件 2021-04-05 12:26:31 +08:00
JaguarJack
5b6e34f3fe update:更新权限列表搜索 2021-04-05 12:26:12 +08:00
JaguarJack
b79b226a74 update:重新渲染system页面 2021-04-03 12:50:21 +08:00
JaguarJack
6ba18dfad2 update:更新action操作 2021-04-03 12:49:55 +08:00
JaguarJack
6630058508 delete:删除冗余 2021-04-03 10:35:53 +08:00
JaguarJack
0bbb39696b update:更新表单action 2021-04-03 10:35:21 +08:00
JaguarJack
7fd87caa36 fixed 2021-04-02 12:05:44 +08:00
JaguarJack
2125966684 fixed:class not found 2021-04-01 20:17:25 +08:00
JaguarJack
4180cb2565 update:更新路由注释,编辑器可追踪 2021-04-01 18:39:11 +08:00
JaguarJack
dffad1e2c4 update:更新菜单列表 2021-03-31 20:44:40 +08:00
JaguarJack
3d70495836 update:更新数据 2021-03-31 20:23:18 +08:00
JaguarJack
6372ccd877 新增路由 2021-03-31 20:21:39 +08:00
JaguarJack
2ad466e617 update:table组件 2021-03-31 20:21:16 +08:00
JaguarJack
5ce104e820 update:form组件 2021-03-31 20:21:02 +08:00
JaguarJack
f56cb943ff add:新增catchTable 2021-03-31 20:20:47 +08:00
JaguarJack
2b96f3b650 update:更新权限系统 2021-03-31 20:20:21 +08:00
JaguarJack
d4020b93a3 add:新增table组件 2021-03-29 19:52:01 +08:00
JaguarJack
2f25a0892e update:更新form功能 2021-03-29 19:51:41 +08:00
JaguarJack
114387d030 update readme 2021-03-28 13:00:20 +08:00
JaguarJack
e3ab44e6d3 fixed:代码生成表失败 2021-03-25 17:51:24 +08:00
Talent.Miao
0d918c9446 修复代码生成Bug 2021-03-25 16:29:46 +08:00
JaguarJack
002ad814e5 fixed:冲突 2021-03-14 07:47:46 +08:00
JaguarJack
b4a1e9bc4e add:新增表单生成 2021-03-14 07:42:01 +08:00
JaguarJack
822ff3874a update:优化代码生成 2021-03-14 07:41:15 +08:00
JaguarJack
78ca9bebc4 rm 2021-03-07 10:52:08 +08:00
JaguarJack
7b7f13536f Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2021-03-06 20:06:28 +08:00
JaguarJack
766a01e766 update:更新快捷搜索 2021-03-06 20:05:20 +08:00
JaguarJack
3196292c85 Merge pull request #28 from tlerbao/patch-1
修复带有表前缀时找不到字段的问题
2021-03-02 08:07:43 +08:00
JaguarJack
f45b9315a9 update:更新aliasField方法,支持数组 2021-03-01 21:02:01 +08:00
JaguarJack
c3b36013d7 fixed:修复附件无法删除 2021-03-01 21:01:37 +08:00
JaguarJack
17491ca7da add: 新增implode方法 2021-03-01 21:00:09 +08:00
Talent.Miao
d1423eb6e8 修复带有表前缀时找不到字段的问题 2021-03-01 09:43:21 +08:00
JaguarJack
c190672603 update:优化代码 2021-02-27 18:31:59 +08:00
JaguarJack
ddf521b62b add:新增 implode 方法 2021-02-27 18:30:40 +08:00
JaguarJack
50c8470d73 update:优化auth 2021-02-22 08:52:39 +08:00
JaguarJack
e9179ee084 update 2021-02-10 08:33:17 +08:00
JaguarJack
adb7ff5a03 fixed:gitee Issue#I37RKN 2021-02-08 17:28:25 +08:00
JaguarJack
706410480b update:优化部分代码 2021-02-08 11:26:54 +08:00
JaguarJack
61ecd0629f update:优化模块信息获取 2021-02-08 11:12:36 +08:00
JaguarJack
84c85c3d12 fixed:修复定时任务立即执行导致任务执行混乱 2021-02-08 10:25:03 +08:00
JaguarJack
d8496f9e62 update:更新自定义权限 2021-02-07 17:21:34 +08:00
JaguarJack
1495a4c731 update:更新crontab 2021-02-07 09:42:01 +08:00
JaguarJack
0efe79ddb3 update:修复多数据库切换之后CatchQuery方法失效 2021-02-05 13:52:23 +08:00
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
yanwenwu
cf1dedabd4 冲突 2019-12-20 22:22:32 +08:00
yanwenwu
fc885476ef 修改 2019-12-20 22:15:45 +08:00
wuyanwen
aefa972804 修改用户管理 2019-12-19 07:23:32 +08:00
wuyanwen
c02f762537 修改权限管理 2019-12-19 07:23:18 +08:00
wuyanwen
122b624580 新增模块创建命令 2019-12-19 07:19:15 +08:00
wuyanwen
7e304cacf0 修改基类 2019-12-19 07:18:39 +08:00
wuyanwen
11854ec33e 修改服务 2019-12-19 07:18:18 +08:00
wuyanwen
a36603f7c2 修改系统管理 2019-12-19 07:17:51 +08:00
wuyanwen
6e0a405f09 修改首页 2019-12-19 07:17:33 +08:00
wuyanwen
2f71ba5380 Merge branch 'master' of https://gitee.com/jaguarjack/catchAdmin 2019-12-18 18:54:07 +08:00
wuyanwen
57f6597e77 添加初始化账号 2019-12-18 18:54:01 +08:00
zhangfayuan
300e536053 Apache环境下出现 No input file specified. 2019-12-18 14:34:45 +08:00
wuyanwen
3d8b31b2dc 修改composer镜像 2019-12-17 13:57:03 +08:00
wuyanwen
4e8aa4ae31 修改error页面 2019-12-17 12:35:25 +08:00
wuyanwen
daf6d1f760 修改响应 2019-12-17 12:35:12 +08:00
wuyanwen
7be9b78ac4 修改readme 2019-12-17 12:21:57 +08:00
wuyanwen
b4a411f343 新增解压包命令 2019-12-17 09:03:32 +08:00
wuyanwen
46a41c86ea 新增layout 2019-12-17 09:03:04 +08:00
wuyanwen
2c349e0832 优化 2019-12-17 09:02:49 +08:00
wuyanwen
5d1da432c7 修改服务 2019-12-17 09:02:29 +08:00
wuyanwen
3e91f16f27 修改继承 2019-12-17 09:02:16 +08:00
wuyanwen
efd0dd8e8f 修改继承 2019-12-17 09:02:09 +08:00
wuyanwen
f1c9f3db53 修改继承 2019-12-17 09:02:00 +08:00
wuyanwen
6f33180f9f 修改 js 2019-12-16 17:28:26 +08:00
wuyanwen
6e73f78bd3 修改 js 2019-12-16 17:25:40 +08:00
wuyanwen
438582ad6a 修改配置 2019-12-15 18:55:41 +08:00
wuyanwen
6caafbf4ca 修改配置 2019-12-15 18:55:14 +08:00
wuyanwen
0bc1b3c30c 修改 2019-12-15 17:47:30 +08:00
wuyanwen
a1c135f5d0 修改 2019-12-15 17:45:47 +08:00
wuyanwen
bfeb14b597 新增子域名设置 2019-12-15 17:27:01 +08:00
wuyanwen
27b30a8704 新增域名路由 2019-12-15 17:26:40 +08:00
wuyanwen
aea9eb6a17 修改路由加载 2019-12-15 15:51:00 +08:00
wuyanwen
0d05e4ecbd 修改exception 2019-12-15 15:50:31 +08:00
wuyanwen
f1ca73e05f 新增清空日志 2019-12-15 15:50:10 +08:00
wuyanwen
b365ec1db8 修改logo地址 2019-12-15 15:13:37 +08:00
wuyanwen
cd16d4314e 替换logo 2019-12-15 15:13:15 +08:00
wuyanwen
aba362dbad 新增基类异常 2019-12-15 13:38:47 +08:00
wuyanwen
79863215b3 修改request 2019-12-15 13:38:25 +08:00
wuyanwen
6c12887f8d 修复登录异常 2019-12-15 13:38:02 +08:00
wuyanwen
a018373013 修改验证码 2019-12-14 23:09:03 +08:00
wuyanwen
a9a857389a 修改登录 2019-12-14 22:59:38 +08:00
wuyanwen
5fec0b01b7 修改基类 2019-12-14 22:55:25 +08:00
wuyanwen
a62b1d54d6 修改服务 2019-12-14 22:55:05 +08:00
wuyanwen
4bfc021cdf 修改首页 2019-12-14 22:54:55 +08:00
wuyanwen
e3ececc277 修改权限路由 2019-12-14 22:54:41 +08:00
wuyanwen
2d6d074d94 修改登录 2019-12-14 22:54:24 +08:00
wuyanwen
6ac4b8784e 新增体验地址 2019-12-14 18:29:08 +08:00
wuyanwen
34d75c3f46 修改路由加载 2019-12-14 18:21:29 +08:00
wuyanwen
d21126882b 修改权限 2019-12-14 18:17:22 +08:00
wuyanwen
d7f0e6c949 新增拦截 2019-12-14 18:16:52 +08:00
wuyanwen
dc5ffd6ab1 修改权限 2019-12-14 18:16:44 +08:00
wuyanwen
d1d497076b 修改 2019-12-14 18:02:09 +08:00
wuyanwen
e6d1517429 修改 2019-12-14 17:59:11 +08:00
wuyanwen
eb2fd14f07 修改备份地址 2019-12-14 17:54:06 +08:00
wuyanwen
1bcc0f217e 修改备份地址 2019-12-14 17:53:40 +08:00
wuyanwen
6724da9e8f 修改基类 2019-12-14 17:50:54 +08:00
wuyanwen
d3e0c64b58 修改权限路由 2019-12-14 17:37:45 +08:00
wuyanwen
722b8cfa7f 修改路由缓存 2019-12-14 17:37:00 +08:00
wuyanwen
0d0abf3ea0 tree-table 2019-12-14 17:08:21 +08:00
wuyanwen
485432acfb 修改路由 2019-12-14 16:56:59 +08:00
wuyanwen
3ec10515fb 修改权限 2019-12-14 16:54:56 +08:00
wuyanwen
d3dfe38d60 发布 2019-12-14 16:02:09 +08:00
wuyanwen
74841b0717 修改readme 2019-12-14 15:57:55 +08:00
wuyanwen
5bcfe3c52d 安装新增数据填充 2019-12-14 15:57:32 +08:00
wuyanwen
6ac0562470 新增用户seed 2019-12-14 15:57:15 +08:00
wuyanwen
d27b7442d8 新增seed 2019-12-14 15:56:59 +08:00
wuyanwen
8479522970 安装修改 2019-12-14 15:03:39 +08:00
wuyanwen
1ce4c7122a 修改安装命令 2019-12-14 14:58:08 +08:00
wuyanwen
e35a76a80e 新增备份 2019-12-13 17:26:54 +08:00
wuyanwen
dacf005117 新增助手函数 2019-12-13 17:26:40 +08:00
wuyanwen
fad0f9770d 新增助手函数 2019-12-13 17:26:19 +08:00
wuyanwen
b5e90dd14f 修改权限管理 2019-12-13 17:26:09 +08:00
wuyanwen
17d30f1cc3 修改系统管理 2019-12-13 17:25:47 +08:00
wuyanwen
a4a03857ac 修改用户管理 2019-12-13 17:25:34 +08:00
wuyanwen
0d0cc6eeb6 修改服务 2019-12-13 17:25:22 +08:00
wuyanwen
d40deeff60 修改app 2019-12-13 17:25:05 +08:00
wuyanwen
6f7e0d71c2 更新公共库 2019-12-12 22:34:27 +08:00
wuyanwen
86a198d66a 注册事件 2019-12-12 22:34:08 +08:00
wuyanwen
5976ebb235 增加操作事件 2019-12-12 22:33:58 +08:00
wuyanwen
02b973d0b5 增加登录事件 2019-12-12 22:33:45 +08:00
wuyanwen
bdbf812941 修改菜单 2019-12-12 22:33:28 +08:00
wuyanwen
15be66ec26 新增系统管理 2019-12-12 22:33:12 +08:00
wuyanwen
d53b0bae73 新增后台基础公共库 2019-12-12 18:54:07 +08:00
wuyanwen
4a5993160f 修改session时间 2019-12-12 18:53:34 +08:00
wuyanwen
67e79bfa19 增加后台配置 2019-12-12 18:53:25 +08:00
wuyanwen
c8eedead00 注册中间件 2019-12-12 18:53:10 +08:00
wuyanwen
109cb7279a 修改登录 2019-12-12 18:52:56 +08:00
wuyanwen
a0a62b5640 增加默认错误页面 2019-12-12 18:52:44 +08:00
wuyanwen
5c7c976869 权限管理 2019-12-12 18:52:33 +08:00
wuyanwen
6c423e5fc5 用户管理 2019-12-12 18:52:24 +08:00
wuyanwen
5f6a7cf24e 增加基础 2019-12-12 18:52:11 +08:00
wuyanwen
ca4272d7a6 公共库 2019-12-12 09:14:08 +08:00
wuyanwen
d154f3e1ac 用户模块 2019-12-12 09:13:53 +08:00
wuyanwen
66e72c6537 登录模块 2019-12-12 09:13:44 +08:00
wuyanwen
7a6628a95f 权限管理 2019-12-12 09:13:29 +08:00
wuyanwen
ecae3e90f1 Merge branch 'master' of https://gitee.com/jaguarjack/catchAdmin 2019-12-11 21:00:27 +08:00
wuyanwen
c48d9154ad 首页 2019-12-11 21:00:24 +08:00
wuyanwen
6624a0cc6b 权限管理 2019-12-11 21:00:14 +08:00
wuyanwen
22064c6178 用户管理 2019-12-11 20:59:59 +08:00
zhangfayuan
7ac37e235b catch-seed:run 2019-12-10 14:03:28 +08:00
wuyanwen
ae7fd47a5d 新增theme 2019-12-09 16:48:09 +08:00
wuyanwen
dfa045726b 修改 2019-12-09 16:22:00 +08:00
wuyanwen
e6b443043a 修改忽略文件 2019-12-09 09:58:52 +08:00
wuyanwen
330a19e8c3 用户管理 2019-12-07 17:31:38 +08:00
wuyanwen
fa4837487b 增加分页响应 2019-12-06 14:44:41 +08:00
wuyanwen
5c7765c97f 扩展功能 2019-12-06 09:17:40 +08:00
wuyanwen
397c8bb7f7 基础功能 2019-12-06 08:24:07 +08:00
wuyanwen
6b4dd70752 用户管理模块 2019-12-03 21:43:37 +08:00
wuyanwen
2651ed6305 修改 2019-12-03 08:15:31 +08:00
wuyanwen
849db90b32 Merge branch 'master' of https://gitee.com/jaguarjack/catchAdmin 2019-12-02 23:05:47 +08:00
wuyanwen
40676f8b14 first commit 2019-12-02 23:04:43 +08:00
wuyanwen
38bcb43e70 删除 2019-12-02 22:58:11 +08:00
651 changed files with 33223 additions and 40751 deletions

View File

@@ -1,15 +0,0 @@
app_debug=true
app_trace=true
db_connection=mysql
db_host=localhost
db_database=thinking
db_username=user
db_port=3306
db_password=password
redis_host=
redis_port=
redis_password=

1
.example.env Normal file
View File

@@ -0,0 +1 @@
APP_DEBUG = false

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

5
.gitignore vendored
View File

@@ -1,7 +1,8 @@
/.idea
/.vscode
/vendor
/package
*.log
thinkphp
.env
.DS_Store
composer.lock

20
LICENSE
View File

@@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2018 JaguarJack
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

201
LICENSE.txt Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
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.

227
README.md
View File

@@ -1,81 +1,164 @@
# think-admin
# ENV
- php >= 7.1.3
- mysql >= 5.5
<p align="center">
<img src="https://cdn.learnku.com/uploads/images/202005/17/18206/zSuf7Ce5kM.png!large">
</p>
# install
- curl -sS http://install.phpcomposer.com/installer | php
- composer config -g repo.packagist composer https://packagist.laravel-china.org
- composer update
- 修改根目录下 .env.emp .env
- .env 配置数据库信息
- php think migrate:run
- php think seed:run
# Use
- 配置虚拟域名 OR 在根目录下执行 php think run
- yourUrl/login
- 默认用户名 admin 密码 admin
<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>
# nginx 配置
<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+ (需以下扩展)
- [x] mbstring
- [x] json
- [x] openssl
- [x] xml
- [x] pdo
- nginx
- mysql
### 如何安装
> 安装之前请确保已安装 Composer
#### 下载项目
- 通过 Git 下载(推荐)
```shell
git clone https://gitee.com/jaguarjack/catchAdmin && cd catchAdmin
curl -sS https://install.phpcomposer.com/installer | php
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
composer install --ignore-platform-reqs
```
server {
listen 端口;
server_name 域名;
access_log logs/wenwen.access.log;
root 项目目录/public;
index index.php index.html index.htm;
location / {
index index.php index.html index.htm;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location ~ \.php$ {
root 项目目录/public;
fastcgi_pass phpfastcgi;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ^~ /data {
deny all;
}
}
- composer 安装
```shell
composer create-project jaguarjack/catchadmin:dev-master
```
# Problem
> SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'updated_at'
设置 sql_mode;
#### 安装
下载完成之后通过命令来进行安装, 一键安装 🚀
```shell
php think catch:install
```
show variables like 'sql_mode' ;
```
> remove 'NO_ZERO_IN_DATE,NO_ZERO_DATE'
```
SET GLOBAL sql_mode='STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
```
# Test Address
<a href="http://tp5.whwww.net" target="__BLANK">测试地址</a>
- 账号admin
- 密码: 123456
# Talking
- 可以提 ISSUE请按照 issue 模板提问
- 欢迎进入 Q 群,可以及时反馈一些问题。
- ![输入图片说明](https://images.gitee.com/uploads/images/2018/1219/110300_0257b6c0_810218.jpeg "微信图片_20181219105915.jpg")
## 体验地址
仅供学习
[体验地址](http://vue.catchadmin.com)
- 账号: catch@admin.com
- 密码: 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">
### Who used
- [uctoo 应用开发管理后台](https://gitee.com/uctoo/uctoo)
### 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)

93
app/BaseController.php Normal file
View File

@@ -0,0 +1,93 @@
<?php
declare (strict_types = 1);
namespace app;
use think\App;
use think\exception\ValidateException;
use think\Validate;
/**
* 控制器基础类
*/
abstract class BaseController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{}
/**
* 验证数据
* @access protected
* @param array $data 数据
* @param string|array $validate 验证器名或者验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array|string|true
* @throws ValidateException
*/
protected function validate(array $data, $validate, array $message = [], bool $batch = false)
{
if (is_array($validate)) {
$v = new Validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
list($validate, $scene) = explode('.', $validate);
}
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
$v->message($message);
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch(true);
}
return $v->failException(true)->check($data);
}
}

57
app/ExceptionHandle.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
namespace app;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use Throwable;
/**
* 应用异常处理类
*/
class ExceptionHandle extends Handle
{
/**
* 不需要记录信息(日志)的异常类列表
* @var array
*/
protected $ignoreReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
DataNotFoundException::class,
ValidateException::class,
];
/**
* 记录异常信息(包括日志或者其它方式记录)
*
* @access public
* @param Throwable $exception
* @return void
*/
public function report(Throwable $exception): void
{
// 使用内置的方式记录异常日志
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @access public
* @param \think\Request $request
* @param Throwable $e
* @return Response
* @throws \Exception
*/
public function render($request, Throwable $e): Response
{
// 其他错误交给系统处理
return parent::render($request, $e);
}
}

53
app/Request.php Normal file
View File

@@ -0,0 +1,53 @@
<?php
namespace app;
// 应用请求对象类
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
{
protected $auth;
/**
* login user
*
* @time 2020年01月09日
* @param null $guard
* @return mixed
*/
public function user($guard = null)
{
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;
}
}

2
app/common.php Normal file
View File

@@ -0,0 +1,2 @@
<?php
// 应用公共文件

18
app/event.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
// 事件定义文件
return [
'bind' => [],
'listen' => [
'AppInit' => [],
'HttpRun' => [],
'HttpEnd' => [],
'LogLevel' => [],
'LogWrite' => [],
'RouteLoaded' => [],
],
'subscribe' => [
],
];

11
app/middleware.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
// 全局中间件定义文件
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
// \think\middleware\SessionInit::class
\think\middleware\AllowCrossDomain::class,
];

9
app/provider.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
use app\ExceptionHandle;
use app\Request;
// 容器Provider定义文件
return [
'think\Request' => Request::class,
'think\exception\Handle' => ExceptionHandle::class,
];

4
app/service.php Normal file
View File

@@ -0,0 +1,4 @@
<?php
return [
\catcher\CatchAdminService::class,
];

View File

@@ -1,48 +0,0 @@
<?php
namespace app\admin\controller;
use think\Controller;
use app\traits\ControllerTrait;
abstract class Base extends Controller
{
use ControllerTrait;
protected $limit = 10;
protected $page = 1;
protected $middleware = ['checkLogin', 'auth', 'logRecord'];
/**
* 过滤参数
*
* @time at 2018年11月15日
* @param $params
* @return void
*/
protected function checkParams(&$params)
{
$this->limit = $params['limit'] ?? $this->limit;
$this->page = $params['page'] ?? $this->page;
foreach ($params as $key => $param) {
if (!$param || $key == 'limit' || $key == 'page') {
unset($params[$key]);
}
}
$this->start = $this->start();
}
/**
* Table ID Start
*
* @time at 2018年11月16日
* @return float|int
*/
protected function start()
{
return (int)$this->limit * ((int)$this->page - 1) + 1;
}
}

View File

@@ -1,63 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/1/18
* Time: 10:36
*/
namespace app\admin\controller;
use think\Db;
class Database extends Base
{
/**
* 数据字典列表
*
* @time at 2019年01月18日
* @return mixed
*/
public function index()
{
$this->tables = Db::query('SHOW TABLE STATUS');
return $this->fetch();
}
/**
* 优化表
*
* @time at 2019年01月18日
* @return void
*/
public function optimize()
{
$table = $this->request->post('table');
if (!$table) {
$this->error('参数错误, 未指定表');
}
Db::query(sprintf('optimize table %s', $table)) ? $this->success('优化成功') : $this->error('优化失败');
}
/**
*
*
* @time at 2019年01月18日
* @return void
*/
public function view()
{
$table = $this->request->param('table');
if (!$table) {
$this->error('参数错误', '未指定表');
}
$this->table = Db::query('show full columns from ' . $table);
return $this->fetch();
}
}

View File

@@ -1,43 +0,0 @@
<?php
namespace app\admin\controller;
use think\permissions\facade\Permissions;
use think\permissions\facade\Roles;
use app\service\MenuService;
class Index extends Base
{
protected $middleware = [ 'checkLogin' ];
/**
* 首页
*
* @time at 2018年11月15日
* @return mixed|string
*/
public function index(MenuService $menuService)
{
$loginUser = $this->getLoginUser();
$userHasRoles = $loginUser->getRoles();
$permissionIds = [];
$userHasRoles->each(function ($role, $key) use (&$permissionIds) {
$permissionIds = array_merge($permissionIds, Roles::getRoleBy($role->id)->getPermissions(false));
});
$permissions = Permissions::whereIn('id', $permissionIds)->where('is_show', 1)->select();
$this->permissions = $menuService->tree($permissions);
$this->loginUser = $loginUser;
return $this->fetch();
}
/**
* main
*
* @time at 2018年11月16日
* @return mixed|string
*/
public function main()
{
return $this->fetch();
}
}

View File

@@ -1,30 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/1/18
* Time: 9:01
*/
namespace app\admin\controller;
use app\model\LogRecordModel;
class Log extends Base
{
/**
* 日志列表
*
* @time at 2019年01月18日
* @param LogRecordModel $logRecordModel
* @return mixed
*/
public function index(LogRecordModel $logRecordModel)
{
$params = $this->request->param();
$this->checkParams($params);
$this->list = $logRecordModel->getAll($params, $this->limit);
return $this->fetch();
}
}

View File

@@ -1,55 +0,0 @@
<?php
namespace app\admin\controller;
use app\traits\Auth;
use think\Controller;
class Login extends Controller
{
use Auth;
protected $redirect = '/index';
/**
* Login Page
*
* @return mixed
*/
public function login()
{
// 登录逻辑
if ($this->request->isPost()) {
$this->authLogin($this->request);
}
return $this->fetch('/index/login');
}
/**
* 登出
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\think\response\Redirect
*/
public function logout()
{
$this->authLogout();
return redirect(url('login'));
}
/**
* 验证规则
*
* @time at 2018年11月13日
* @return array
*/
protected function rule()
{
return [
$this->name() => 'require',
'password|密码' => 'require',
'captcha|验证码' => 'require|captcha'
];
}
}

View File

@@ -1,78 +0,0 @@
<?php
namespace app\admin\controller;
use think\Collection;
use think\permissions\facade\Permissions;
use app\admin\request\PermissionRequest;
use app\service\MenuService;
class Permission extends Base
{
public function index(MenuService $menuService)
{
$this->permissions = new Collection($menuService->sort(Permissions::select()));
return $this->fetch();
}
/**
* Create Data
*
* @time at 2018年11月13日
* @return mixed|string
*/
public function create(PermissionRequest $request, MenuService $menuService)
{
if ($request->isPost()) {
$data = $request->post();
Permissions::store($data) ? $this->success('添加成功', url('permission/index')) : $this->error('添加失败');
}
$this->permissions = $menuService->sort(Permissions::select());
$this->permissionId = $this->request->param('id') ?? 0;
return $this->fetch();
}
/**
* Edit Data
*
* @time at 2018年11月13日
* @return mixed|string
*/
public function edit(PermissionRequest $request, MenuService $menuService)
{
if ($request->isPost()) {
$data = $request->post();
Permissions::updateBy($data['id'], $data) !== false ? $this->success('编辑成功', url('permission/index')) : $this->error('');
}
$permissionId = $this->request->param('id');
if (!$permissionId) {
$this->error('不存在的数据');
}
$this->permissions = $menuService->sort(Permissions::select());
$this->permission = Permissions::getPermissionBy($permissionId);
return $this->fetch();
}
/**
* Delete Data
*
* @time at 2018年11月13日
* @return void
*/
public function delete()
{
$permissionId = $this->request->post('id');
if (!$permissionId) {
$this->error('不存在数据');
}
if (Permissions::where('pid', $permissionId)->find()) {
$this->error('请先删除子菜单');
}
// 删除权限关联的角色信息
Permissions::detachRole($permissionId);
if (Permissions::deleteBy($permissionId)) {
$this->success('删除成功', url('permission/index'));
}
$this->error('删除失败');
}
}

View File

@@ -1,115 +0,0 @@
<?php
namespace app\admin\controller;
use think\permissions\facade\Roles;
use app\admin\request\RoleRequest;
use think\permissions\facade\Permissions;
use app\service\MenuService;
class Role extends Base
{
public function index()
{
$this->roles = Roles::paginate(10);
return $this->fetch();
}
/**
* create Data
*
* @time at 2018年11月13日
* @return mixed|string
*/
public function create(RoleRequest $request)
{
if ($request->isPost()) {
Roles::store($request->post()) ? $this->success('创建成功', url('role/index')) : $this->error('创建失败');
}
return $this->fetch();
}
/**
* Edit Data
*
* @time at 2018年11月13日
* @return mixed|string
*/
public function edit(RoleRequest $request)
{
if ($this->request->isPost()) {
Roles::updateBy($request->post('id'), $request->post()) !== false ? $this->success('编辑成功', url('role/index')) : $this->error('编辑失败');
}
$this->role = Roles::getRoleBy($this->request->param('id'));
return $this->fetch();
}
/**
* Delete Data
*
* @time at 2018年11月13日
* @return void
*/
public function delete()
{
$roleId = $this->request->post('id');
if (!$roleId) {
$this->error('角色信息不存在');
}
// 删除角色相关的用户
Roles::detachUsers($roleId);
// 删除角色相关的权限
Roles::detachPermissions($roleId);
if (Roles::deleteBy($roleId)) {
$this->success('删除成功', url('role/index'));
}
$this->error('删除失败');
}
/**
* 获取角色权限
*
* @time at 2018年09月21日
* @return void
*/
public function getPermissionsOfRole(MenuService $menuService)
{
$field = ['name', 'id', 'pid'];
$roleId = $this->request->post('role_id');
$permissions = Permissions::field($field)->all();
$roleHasPermissions = Roles::getRoleBy($roleId)->getPermissions(false);
$permissions = $permissions->each(function ($item, $key) use ($roleHasPermissions){
if (!$item->pid) {
$item->open = true;
}
$item->checked = in_array($item->id, $roleHasPermissions) ? true : false;
return $item;
});
header('content-Type: application/json');
exit(json_encode($menuService->sort($permissions)));
}
/**
* 分配权限
*
* @time at 2018年11月15日
* @return mixed|string
*/
public function givePermissions()
{
if ($this->request->isPost()) {
$postData = $this->request->post();
$roleId = $postData['role_id'];
if (!isset($postData['permissions'])) {
Roles::detachPermissions($roleId);
$this->success('分配成功', url('role/index'));
}
$permissions = $postData['permissions'];
Roles::detachPermissions($roleId);
Roles::attachPermissions($roleId, $permissions) ? $this->success('分配成功', url('role/index')) : $this->error('分配失败');
}
$this->role_id = $this->request->param('id');
return $this->fetch('role/givePermissions');
}
}

View File

@@ -1,126 +0,0 @@
<?php
namespace app\admin\controller;
use app\model\UserModel;
use app\admin\request\UserRequest;
use think\permissions\facade\Roles;
class User extends Base
{
/**
* User List
*
* @time at 2018年11月12日
* @return mixed|string
*/
public function index(UserModel $userModel)
{
$params = $this->request->param();
$this->checkParams($params);
$this->users = $userModel->getList($params, $this->limit);
return $this->fetch();
}
/**
* create Data
*
* @time at 2018年11月12日
* @return mixed|string
*/
public function create(UserModel $userModel, UserRequest $request)
{
if ($request->isPost()) {
$data = $request->post();
$data['password'] = generatePassword($data['password']);
if ($userId = $userModel->store($data)) {
// 分配角色
$this->giveRoles($userModel, $userId, $data);
$this->success('添加成功', url('user/index'));
}
$this->error('添加失败');
}
$this->roles = Roles::all();
return $this->fetch();
}
/**
* Edit Data
*
* @time at 2018年11月12日
* @return mixed|string
*/
public function edit(UserModel $userModel, UserRequest $request)
{
if ($request->isPost()) {
$data = $request->post();
$this->giveRoles($userModel, $data['id'], $data);
$data['password'] = generatePassword($data['password']);
$userModel->updateBy($data['id'], $data) ? $this->success('修改成功', url('user/index')) : $this->error('修改失败');
}
$id = $this->request->param('id');
if (!$id) {
$this->error('数据不存在');
}
$user = $userModel->findBy($id);
$userHasRoles = $user->getRoles(false);
$roles = Roles::all()->each(function($item, $key) use ($userHasRoles){
$item->checked = in_array($item->id, $userHasRoles) ? true : false;
return $item;
});
$this->user = $user;
$this->roles = $roles;
return $this->fetch();
}
/**
* Delete Data
*
* @time at 2018年11月12日
* @return void
*/
public function delete(UserModel $userModel)
{
$id = $this->request->post('id');
if (!$id) {
$this->error('不存在的数据');
}
// 删除用户相关的角色
$userModel->detachRoles($id);
if ($userModel->deleteBy($id)) {
$this->success('删除成功', url('user/index'));
}
$this->error('删除失败');
}
/**
* 分配角色
*
* @time at 2018年11月15日
* @param \app\model\UserModel $userModel
* @param int $userId
* @param $data
* @return bool
*/
protected function giveRoles(UserModel $userModel, int $userId, &$data)
{
if (isset($data['roles'])) {
$rolesIds = $data['roles'];
if (!is_array($rolesIds)) {
$rolesIds = [$rolesIds];
}
$userModel->detachRoles($userId);
$userModel->attachRoles($userId, $rolesIds);
unset($data['roles']);
return true;
}
$userModel->detachRoles($userId);
return true;
}
}

View File

@@ -1,30 +0,0 @@
<?php
/**
* UserRequest.php
* Created by wuyanwen <wuyanwen1992@gmail.com>
* Date: 2018/11/29 0029 21:56
*/
namespace app\admin\request;
use think\exception\HttpResponseException;
use think\Request;
abstract class FormRequest extends Request
{
/**
* FormRequest constructor.
*/
public function __construct()
{
parent::__construct();
if ($this->withServer($_SERVER)->isAjax(true) && $err = $this->validate()) {
throw new HttpResponseException(json([
'code' => 0,
'msg' => $err,
'wait' => 3,
]));
}
}
}

View File

@@ -1,17 +0,0 @@
<?php
/**
* UserRequest.php
* Created by wuyanwen <wuyanwen1992@gmail.com>
* Date: 2018/11/29 0029 21:56
*/
namespace app\admin\request;
use app\admin\validates\PermissionValidate;
class PermissionRequest extends FormRequest
{
public function validate()
{
return (new PermissionValidate())->getErrors($this->post());
}
}

View File

@@ -1,17 +0,0 @@
<?php
/**
* UserRequest.php
* Created by wuyanwen <wuyanwen1992@gmail.com>
* Date: 2018/11/29 0029 21:56
*/
namespace app\admin\request;
use app\admin\validates\RoleValidate;
class RoleRequest extends FormRequest
{
public function validate()
{
return (new RoleValidate())->getErrors($this->post());
}
}

View File

@@ -1,17 +0,0 @@
<?php
/**
* UserRequest.php
* Created by wuyanwen <wuyanwen1992@gmail.com>
* Date: 2018/11/29 0029 21:56
*/
namespace app\admin\request;
use app\admin\validates\UserValidate;
class UserRequest extends FormRequest
{
public function validate()
{
return (new UserValidate())->getErrors($this->post());
}
}

View File

@@ -1,35 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/12 0012
* Time: 下午 16:31
*/
namespace app\admin\validates;;
use think\Validate;
abstract class AbstractValidate extends Validate
{
/**
* Get Validate Errors
*
* @time at 2018年11月12日
* @param $data
* @return array
*/
public function getErrors($data)
{
$this->check($data);
return $this->getError();
}
public function __set($name, $value)
{
// TODO: Implement __set() method.
$this->rule[$name] = $value;
}
}

View File

@@ -1,19 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/14 0014
* Time: 下午 18:21
*/
namespace app\admin\validates;
class PermissionValidate extends AbstractValidate
{
protected $rule = [
'name|菜单名称' => 'require|min:2|max:10|chs|unique:permissions',
'module|模块名称' => 'require|min:2|max:10|alpha',
'controller|控制器名称' => 'require|min:2|max:50|alpha',
'action|方法名称' => 'require|min:2|max:50|alpha',
];
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/14 0014
* Time: 下午 17:42
*/
namespace app\admin\validates;
class RoleValidate extends AbstractValidate
{
protected $rule = [
'name|角色名' => 'require|min:3|max:15|chs|unique:roles',
];
}

View File

@@ -1,18 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/12 0012
* Time: 下午 16:38
*/
namespace app\admin\validates;
class UserValidate extends AbstractValidate
{
protected $rule = [
'name|用户名' => 'require|min:3|max:15|alphaNum|unique:users',
'email|邮箱' => 'email|unique:users',
'password|密码' => 'confirm|min:6|max:20|alphaDash',
];
}

View File

@@ -1,20 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/13 0013
* Time: 上午 9:33
*/
namespace app\behavior;
class LoginRecord
{
public function run($params)
{
$user = $params['user'];
## 登录记录
$user->login_at = date('Y-m-d h:i:s', time());
$user->login_ip = request()->ip();
$user->save();
}
}

View File

@@ -1,154 +0,0 @@
<?php
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\DB;
class MakeCurd extends Command
{
protected $appPath;
protected $stubPath;
// view 默认的三个模板
protected $views = ['index', 'create', 'edit'];
public function __construct()
{
parent::__construct();
$this->appPath = env('app_path');
$this->stubPath = $this->appPath . 'command' . DIRECTORY_SEPARATOR . 'stub' .DIRECTORY_SEPARATOR;
}
protected function configure()
{
$this->setName('make:curd')
->addArgument('controller', Argument::OPTIONAL, "controller name")
->addArgument('model', Argument::OPTIONAL, "model name")
->addOption('module', null, Option::VALUE_REQUIRED, 'module name')
->setDescription('Create curd option controller model --module?');
}
protected function execute(Input $input, Output $output)
{
// 首先获取默认模块
$moduleName = config('app.default_module');
$controllerName = trim($input->getArgument('controller'));
if (!$controllerName) {
$output->writeln('Controller Name Must Set');exit;
}
$modelName = trim($input->getArgument('model'));
if (!$modelName) {
$output->writeln('Model Name Must Set');exit;
}
if ($input->hasOption('module')) {
$moduleName = $input->getOption('module');
}
$this->makeController($controllerName, $moduleName);
$output->writeln($controllerName . ' controller create success');
$this->makeModel($modelName, $moduleName);
$output->writeln($modelName . ' model create success');
$this->makeView($controllerName, $moduleName);
$output->writeln($controllerName . ' view create success');
}
// 创建控制器文件
protected function makeController($controllerName, $moduleName)
{
$controllerStub = $this->stubPath . 'Controller.stub';
$controllerStub = str_replace(['$controller', '$module'], [ucfirst($controllerName), strtolower($moduleName)], file_get_contents($controllerStub));
$controllerPath = $this->appPath . $moduleName . DIRECTORY_SEPARATOR . 'controller' . DIRECTORY_SEPARATOR;
if (!is_dir($controllerPath)) {
mkdir($controllerPath, 0777, true);
}
return file_put_contents( $controllerPath . $controllerName . '.php', $controllerStub);
}
// 创建模型文件
public function makeModel($modelName, $moduleName)
{
$modelPath = $this->appPath . DIRECTORY_SEPARATOR . 'model';
if (!is_dir($modelPath)) {
mkdir($modelPath, 0777, true);
}
$modelContents = "<?php \r\n \r\n";
$modelContents .= "namespace app\model;\r\n \r\n";
$modelContents .= 'class $modelModel extends BaseModel';
$modelContents .= "\r\n { \r\n \t";
$modelContents .= 'protected $table = \'' . config('database.prefix') . '$_table\';';
$modelContents = $this->writeField($modelContents, $modelName);
$modelContents = str_replace('$model', ucfirst($modelName), $modelContents);
$modelContents = str_replace('$_table', $this->unCamelize($modelName), $modelContents);
$modelContents .= "\r\n }";
return file_put_contents($modelPath . DIRECTORY_SEPARATOR . $modelName . 'Model.php', $modelContents);
}
private function writeField($modelContents, $modelName)
{
$info = Db::query('show full columns from ' . config('database.prefix') . $this->unCamelize($modelName));
foreach ($info as $value) {
$modelContents .= sprintf("\r\n %s \t protected $%s = '%s'; \r\n", $this->fieldComment($value['Comment']), $this->combine($value['Field']), $value['Field']);
}
return $modelContents;
}
// 创建模板
public function makeView($controllerName, $moduleName)
{
$viewStub = $this->stubPath . 'View.stub';
$viewPath = (config('template.view_base') ? config('template.view_base') . $moduleName . DIRECTORY_SEPARATOR : env('app_path') . $moduleName . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR) . strtolower($controllerName);
if (!is_dir($viewPath)) {
mkdir($viewPath, 0777, true);
}
$stub = explode('||', file_get_contents($viewStub));
foreach ($this->views as $view) {
if ($view == 'index') {
file_put_contents($viewPath . DIRECTORY_SEPARATOR . $view .'.html', trim($stub[0]));
} else {
file_put_contents($viewPath . DIRECTORY_SEPARATOR . $view .'.html', trim($stub[1]));
}
}
}
/**
* 字符注释
*
* @time at 2019年01月08日
* @param $comment
* @return string
*/
private function fieldComment($comment)
{
return sprintf("\t /** \r\n \t * @var string \r\n \t * @desc %s \r\n \t */ \r\n", $comment);
}
/**
* 驼峰分割
*
* @time at 2019年01月02日
* @param string $camelCaps
* @param string $separator
* @return string
*/
private function unCamelize(string $string, string $separator = '_')
{
return strtolower(preg_replace('/(?<=[a-z])([A-Z])/', $separator . '$1', $string));
}
private function combine(string $string)
{
$s = explode('_', $string);
array_walk($s, function (&$value, $key) {
if ($key) {
$value = ucfirst($value);
}
});
return implode($s, '');
}
}

View File

@@ -1,20 +0,0 @@
<?php
namespace app\$module\controller;
class $controller extends Base
{
public function index()
{
return $this->fetch();
}
public function create()
{
return $this->fetch();
}
public function edit()
{
return $this->fetch();
}
public function delete()
{}
}

View File

@@ -1,12 +0,0 @@
{extend name="public:base" /}
{block name="menu"}{/block}
{block name="search"}{/block}
{block name="button-create"}{/block}
{block name="table-head"}{/block}
{block name="table-body"}{/block}
{block name="paginate"}{/block}
||
{extend name="public:form" /}
{block name="menu"}{/block}
{block name='action'}{/block}
{block name="form"}{/block}

View File

@@ -1,67 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用公共文件
/**
* 钩子行为
*/
if (!function_exists('hook')) {
function hook($behavior, $params) {
\think\facade\Hook::exec($behavior, $params);
}
}
/**
* 编辑按钮
*/
if (!function_exists('editButton')) {
function editButton(string $url, string $name = '编辑') {
return sprintf('<a href="%s"><button class="btn btn-info btn-xs edit" type="button"><i class="fa fa-paste"></i> %s</button></a>', $url, $name);
}
}
/**
* 增加按钮
*/
if (!function_exists('createButton')) {
function createButton(string $url, string $name, $isBig = true) {
return $isBig ? sprintf('<a href="%s"> <button type="button" class="btn btn-w-m btn-primary"><i class="fa fa-check-square-o"></i> %s</button></a>', $url, $name) :
sprintf('<a href="%s"> <button type="button" class="btn btn-xs btn-primary"><i class="fa fa-check-square-o"></i> %s</button></a>', $url, $name);
}
}
/**
* 删除按钮
*/
if (!function_exists('deleteButton')) {
function deleteButton(string $url, int $id, string $name="删除") {
return sprintf('<button class="btn btn-danger btn-xs delete" data-url="%s" data=%d type="button"><i class="fa fa-trash"></i> %s</button>', $url, $id, $name);
}
}
/**
* 搜索按钮
*/
if (!function_exists('searchButton')) {
function searchButton(string $name="搜索") {
return sprintf('<button class="btn btn-white" type="submit"><i class="fa fa-search"></i> %s</button>', $name);
}
}
/**
* 生成密码
*/
if (!function_exists('generatePassword')) {
function generatePassword(string $password, int $algo = PASSWORD_DEFAULT) {
return password_hash($password, $algo);
}
}

View File

@@ -1,60 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/16 0016
* Time: 下午 14:51
*/
namespace app\component\upload;
use think\exception\ThrowableError;
use think\facade\Request;
use app\exceptions\UploadException;
class LocalUpload implements UploadInterface
{
protected $name = null;
/**
* Upload File
*
* @time at 2018年11月16日
* @return string
*/
public function file(){}
/**
* Upload Image
*
* @time at 2018年11月16日
* @return string
*/
public function image()
{
try {
$file = Request::file($this->name);
if (!$this->name) {
throw new UploadException('请选择上传的图片');
}
$info = $file->validate(config('admin.image'))->move(config('admin.local_upload_path'));
if (!$info) {
throw new UploadException($file->getError());
}
return $info->getSaveName();
} catch (UploadException $exception) {
return $exception->getMessage();
}
}
/**
* Set Image Name
*
* @time at 2018年11月16日
* @param $name
* @return $this
*/
public function name($name)
{
$this->name = $name;
return $this;
}
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/16 0016
* Time: 下午 14:50
*/
namespace app\component\upload;
interface UploadInterface
{
public function file();
public function image();
}

View File

@@ -1,13 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/13 0013
* Time: 上午 10:49
*/
namespace app\exceptions;
class AppException extends \Exception
{
}

View File

@@ -1,14 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/16 0016
* Time: 下午 15:03
*/
namespace app\exceptions;
class UploadException extends \Exception
{
}

View File

@@ -1,15 +0,0 @@
<?php
namespace app\http\middleware;
class CheckLogin
{
public function handle($request, \Closure $next)
{
if (!$request->session('user')) {
return redirect(url('login'));
}
return $next($request);
}
}

View File

@@ -1,16 +0,0 @@
<?php
namespace app\http\middleware;
use app\service\LogService;
class LogRecord
{
public function handle($request, \Closure $next)
{
(new LogService())->record($request);
return $next($request);
}
}

View File

@@ -1,64 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/12 0012
* Time: 上午 11:05
*/
namespace app\model;
use think\Model;
class BaseModel extends Model
{
const LIMIT = 10;
/**
* Store Data
*
* @time at 2018年11月12日
* @param array $data
* @return bool
*/
public function store(array $data)
{
return $this->save($data) ? $this->id : false;
}
/**
* Find By ID
*
* @time at 2018年11月12日
* @param int $id
* @return array|false|\PDOStatement|string|\think\Model
*/
public function findBy(int $id)
{
return $this->where('id', $id)->find();
}
/**
* Update By ID && Data
*
* @time at 2018年11月12日
* @param int $id
* @param array $data
* @return bool
*/
public function updateBy(int $id, array $data)
{
return $this->save($data, ['id' => $id]);
}
/**
* Delete By ID
*
* @time at 2018年11月12日
* @param int $id
* @return bool|null
*/
public function deleteBy(int $id)
{
return $this->where('id', $id)->delete();
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/1/17
* Time: 18:09
*/
namespace app\model;
use http\Env\Request;
class LogRecordModel extends BaseModel
{
protected $name = 'option_log';
/**
* 日志列表
*
* @time at 2019年01月18日
* @param array $params
* @param int $limit
* @return mixed
*/
public function getAll(array $params, $limit = self::LIMIT)
{
if (!count($params)) {
return $this->order('created_at', 'desc')->paginate($limit, false, ['query' => request()->param()]);
}
if (isset($params['name'])) {
$list = $this->whereLike('user_name', '%'.$params['name'].'%');
}
return $list->order('created_at', 'desc')->paginate($limit, false, ['query' => request()->param()]);
}
}

View File

@@ -1,37 +0,0 @@
<?php
namespace app\model;
use think\permissions\traits\hasRoles;
class UserModel extends BaseModel
{
use hasRoles;
protected $name = 'users';
/**
* Users List
*
* @time at 2018年11月14日
* @param $params
* @return \think\Paginator
*/
public function getList($params, $limit = self::LIMIT)
{
if (!count($params)) {
return $this->paginate($limit);
}
if (isset($params['name'])) {
$user = $this->whereLike('name', '%'.$params['name'].'%');
}
if (isset($params['email'])) {
$user = $this->whereLike('email', '%'.$params['email'].'%');
}
return $user->paginate($limit, false, ['query' => request()->param()]);
}
}

View File

@@ -1,35 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/1/17
* Time: 18:06
*/
namespace app\service;
use think\permissions\facade\Permissions;
use think\Request;
use app\model\LogRecordModel;
class LogService
{
public function record(Request $request)
{
$module = $request->module();
$controller = $request->controller();
$action = $request->action();
$user = $request->session('user');
$permission = Permissions::getPermissionByModuleAnd($module, $controller, $action);
(new LogRecordModel())->store([
'user_id' => $user->id,
'user_name' => $user->name,
'module' => $module,
'controller' => $controller,
'action' => $action,
'option' => $permission->name,
'method' => $request->method(),
]);
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/13 0013
* Time: 上午 10:50
*/
namespace app\service;
use think\Collection;
class MenuService
{
/**
* 树形结构
*
* @time at 2018年11月13日
* @param $menu
* @return Collection
*/
public function tree(Collection $menus, int $pid = 0)
{
$collection = new Collection();
$menus->each(function ($item, $key) use ($pid, $menus, $collection){
if ($item->pid == $pid) {
$collection[$key] = $item;
$collection[$key][$item->id] = $this->tree($menus, $item->id);
}
});
return $collection;
}
/**
* 顺序结构
*
* @time at 2018年11月13日
* @param $menu
* @return Collection
*/
public function sort(Collection $menus, int $pid = 0, int $level = 0)
{
$collection = [];
foreach ($menus as $menu) {
if ($menu->pid == $pid) {
$menu->level = $level;
$collection[] = $menu;
$collection = array_merge($collection, $this->sort($menus, $menu->id, $level+1));
}
}
return $collection;
}
}

View File

@@ -1,63 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/16 0016
* Time: 上午 11:01
*/
namespace app\service;
use think\paginator\driver\Bootstrap;
class PaginateService extends Bootstrap
{
/**
* 渲染分页html
* @return mixed
*/
public function render()
{
if ($this->hasPages()) {
if ($this->simple) {
return sprintf(
'<ul class="pager">%s %s</ul>',
$this->getPreviousButton(),
$this->getNextButton()
);
} else {
return sprintf(
'<ul class="pagination">%s %s %s %s</ul>',
$this->getPreviousButton(),
$this->getLinks(),
$this->getNextButton(),
$this->changeLimit()
);
}
}
}
protected function changeLimit()
{
$query = $this->options['query'];
$html = '&nbsp;<li class="project_page">';
$pageLimit = config('admin.page_limit');
$html .= '<select class="page-form-control limit" name="limit">';
foreach ($pageLimit as $limit) {
if (isset($query['limit']) && $query['limit'] == $limit) {
$html .= sprintf('<option value="%s" selected>%s条/页</option>', $limit, $limit);
} else {
$html .= sprintf('<option value="%s">%s条/页</option>', $limit, $limit);
}
}
$html .= '</select></li>&nbsp;<li>';
$html .= sprintf('<input name="page" class="page-form-control-input" value="%s"> 页 ', $query['page'] ?? 1);
$html .='</li>';
$html .= '<li><button class="btn btn-primary btn-xs hrefTo"><i class="fa fa-location-arrow"></i> 跳转</button></li>';
return $html;
}
}

View File

@@ -1,28 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用行为扩展定义文件
return [
// 应用初始化
'app_init' => [],
// 应用开始
'app_begin' => [],
// 模块初始化
'module_init' => [],
// 操作开始执行
'action_begin' => [],
// 视图内容过滤
'view_filter' => [],
// 日志写入
'log_write' => [],
// 应用结束
'app_end' => [],
];

View File

@@ -1,183 +0,0 @@
<?php
namespace app\traits;
use think\Request;
use think\Validate;
use think\facade\Session;
use think\facade\Cookie;
use app\model\UserModel as User;
use app\behavior\LoginRecord;
trait Auth
{
protected $loginUserKey = 'user';
public function authLogin(Request $request)
{
$err = $this->validateLogin($request);
if ($err) {
$this->error($err);
}
// 正常输入登录
$userModel = new User();
$field = explode('|', $this->name());
$user = $userModel::where($field[0], $request->param($field[0]))->find();
if (!$user) {
$this->error('登录失败');
}
if (password_verify($request->param('password'), $user->password)) {
Session::set($this->loginUserKey, $user);
# 记住登录
$this->LoginRemember($user, $request);
# 登录记录
hook(LoginRecord::class, ['user' => $user]);
$this->success('登录成功', url($this->redirect));
}
$this->error('登录失败');
}
/**
* 记住登录
* @return bool
*/
public function rememberLogin()
{
// 如果记住登录
if (!Session::get($this->loginUserKey) && Cookie::get('remember_token') && $this->checkRememberToken()) {
return true;
}
return false;
}
/**
* 退出
* @return void
*/
public function authLogout()
{
$user = Session::get($this->loginUserKey);
$this->deleteToken($user);
Session::delete($this->loginUserKey);
}
protected function deleteToken($user)
{
if ($user->remember_token) {
$user->remember_token = null;
$user->save();
Cookie::delete('remember_token');
}
}
/**
* 验证
* @param Request $request
* @return array|bool
*/
protected function validateLogin(Request $request)
{
$validate = new Validate($this->rule());
if (!$validate->check($request->except(['remember']))) {
return $validate->getError();
}
return false;
}
/**
* 登录验证规则
* @return array
*/
protected function rule()
{
return [
$this->name() => 'require|token|alphaDash',
'password|密码' => 'require|alphaDash',
'captcha|验证码' => 'require|captcha'
];
}
/**
* 设置登录字段
*
* @return string
*/
protected function name()
{
return 'name|用户名';
}
/**
* Remember Token
*
* @return string
*/
public function generateRememberToken()
{
return uniqid(md5(time()+rand(10000, 99999)));
}
/**
* 加密 TOKEN
*
* @param $user_id
* @param $remember_token
* @return string
*/
protected function secretRememberToken($user_id, $remember_token)
{
list($key, $method, $iv) = $this->getSecret();
return base64_encode(openssl_encrypt($user_id . ':' . $remember_token, $method, $key, OPENSSL_RAW_DATA, $iv));
}
/**
* 检查remember token 是否正确
*
* @return bool
*/
protected function checkRememberToken()
{
if (!Cookie::has('remember_token')) {
return false;
}
$rememberToken = Cookie::get('remember_token');
// 解密
list($key, $method, $iv) = $this->getSecret();
list($userID) = explode(':', (openssl_decrypt(base64_decode($rememberToken), $method, $key, OPENSSL_RAW_DATA, $iv)));
// 校验
$user = (new User())->findBy($userID);
Session::set('user', $user);
return $user->remember_token == $rememberToken;
}
/**
* 加密
*
* @return array
*/
protected function getSecret()
{
return ['admin_auth', 'AES-128-CBC', '1234567890123412'];
}
/**
* 记住
*
* @param $user
* @return void
*/
protected function LoginRemember($user, Request $request)
{
if ($request->has('remember')) {
$rememberToken = $this->secretRememberToken($user->id, $this->generateRememberToken());
$user->remember_token = $rememberToken;
Cookie::forever('remember_token', $rememberToken);
}
}
}

View File

@@ -1,80 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/12 0012
* Time: 上午 11:43
*/
namespace app\traits;
use think\facade\Session;
use app\component\upload\UploadInterface;
use app\component\upload\LocalUpload;
trait ControllerTrait
{
protected $vars = [];
/**
* 绑定实现
*
* @time at 2018年11月16日
* @return void
*/
public function initialize()
{
bind(UploadInterface::class, LocalUpload::class);
}
/**
* 是否登录
*
* @time at 2018年11月15日
* @return bool
*/
protected function isLogin()
{
return $this->getLoginUser() ? true : false;
}
/**
* 获取登录用户
*
* @time at 2018年11月15日
* @return mixed
*/
protected function getLoginUser()
{
return Session::get('user');
}
/**
* fetch 重写
*
* @time at 2018年11月15日
* @param string $template
* @param array $vars
* @param array $config
* @return mixed
*/
protected function fetch($template = '', $vars = [], $config = [])
{
$vars = array_merge($this->vars, $vars);
return $this->view->fetch($template, $vars, $config);
}
/**
* Set Template Vars
*
* @time at 2018年11月12日
* @param $name
* @param $value
* @return void
*/
public function __set($name, $value)
{
// TODO: Implement __set() method.
$this->vars[$name] = $value;
}
}

View File

@@ -1,26 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// 生成应用公共文件
'__file__' => ['common.php'],
// 定义demo模块的自动生成 (按照实际定义的文件名生成)
'demo' => [
'__file__' => ['common.php'],
'__dir__' => ['behavior', 'controller', 'model', 'view'],
'controller' => ['Index', 'Test', 'UserType'],
'model' => ['User', 'UserType'],
'view' => ['index/index'],
],
// 其他更多的模块定义
];

View File

@@ -0,0 +1,47 @@
<?php
namespace catchAdmin\cms\table;
use catcher\CatchTable;
use catcher\library\table\Actions;
use catcher\library\table\HeaderItem;
use catcher\library\table\Search;
class Category extends CatchTable
{
public function table()
{
// TODO: Implement table() method.
return $this->getTable('category')
->header([
HeaderItem::label('分类名称')->prop('name'),
HeaderItem::label('自定义链接')->prop('url'),
HeaderItem::label('栏目类型')->prop('type')->component('type'),
HeaderItem::label('投稿')->prop('is_can_contribute')->withSwitchComponent(),
HeaderItem::label('评论')->prop('is_can_comment')->withSwitchComponent(),
HeaderItem::label('状态')->prop('status')->withSwitchComponent(),
HeaderItem::label('权重')->prop('weight')->withEditNumberComponent(),
HeaderItem::label('创建时间')->prop('created_at'),
HeaderItem::label('操作')->actions([
Actions::update(),
Actions::delete()
])
])
->withActions([
Actions::create()
])
->withSearch([
Search::label('分类名称')->name('请输入分类名称'),
Search::label('状态')->name('请选择状态'),
])
->toTreeTable()
->render();
}
public function form()
{
// TODO: Implement form() method.
}
}

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,100 @@
<?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' => 82,
'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' => 1612754299,
'deleted_at' => 0,
'children' =>
array (
0 =>
array (
'id' => 83,
'permission_name' => '域名设置',
'parent_id' => 82,
'level' => '82',
'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' => 1612754299,
'deleted_at' => 0,
),
1 =>
array (
'id' => 84,
'permission_name' => '域名记录',
'parent_id' => 82,
'level' => '82',
'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' => 1612754299,
'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
}

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

@@ -0,0 +1,24 @@
<?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 ]
// +----------------------------------------------------------------------
/* @var think\Route $router */
// 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

@@ -0,0 +1,80 @@
<?php
namespace catchAdmin\login;
use catchAdmin\permissions\model\Users;
use catchAdmin\system\model\LoginLog;
use think\facade\Db;
class LoginLogEvent
{
public function handle($params)
{
$agent = request()->header('user-agent');
app(LoginLog::class)->storeBy([
'login_name' => $params['login_name'],
'login_ip' => request()->ip(),
'browser' => $this->getBrowser($agent),
'os' => $this->getOs($agent),
'login_at' => time(),
'status' => $params['success'],
]);
}
/**
*
* @time 2019年12月12日
* @param $agent
* @return string
*/
private function getOs($agent): string
{
if (false !== stripos($agent, 'win') && preg_match('/nt 6.1/i', $agent)) {
return 'Windows 7';
}
if (false !== stripos($agent, 'win') && preg_match('/nt 6.2/i', $agent)) {
return 'Windows 8';
}
if(false !== stripos($agent, 'win') && preg_match('/nt 10.0/i', $agent)) {
return 'Windows 10';#添加win10判断
}
if (false !== stripos($agent, 'win') && preg_match('/nt 5.1/i', $agent)) {
return 'Windows XP';
}
if (false !== stripos($agent, 'linux')) {
return 'Linux';
}
if (false !== stripos($agent, 'mac')) {
return 'mac';
}
return '未知';
}
/**
*
* @time 2019年12月12日
* @param $agent
* @return string
*/
private function getBrowser($agent): string
{
if (false !== stripos($agent, "MSIE")) {
return 'MSIE';
}
if (false !== stripos($agent, "Firefox")) {
return 'Firefox';
}
if (false !== stripos($agent, "Chrome")) {
return 'Chrome';
}
if (false !== stripos($agent, "Safari")) {
return 'Safari';
}
if (false !== stripos($agent, "Opera")) {
return 'Opera';
}
return '未知';
}
}

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

@@ -0,0 +1,26 @@
<?php
namespace catchAdmin\login\request;
use catcher\base\CatchRequest;
class LoginRequest extends CatchRequest
{
protected $needCreatorId = false;
protected function rules(): array
{
// TODO: Implement rules() method.
return [
'email|用户名' => 'email',
'password|密码' => 'require',
// 'captcha|验证码' => 'require|captcha'
];
}
protected function message(): array
{
// TODO: Implement message() method.
return [];
}
}

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

@@ -0,0 +1,12 @@
<?php
/* @var think\Route $router */
$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,128 @@
<?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)
->select()
->each(function ($command) use (&$executeAbleCommands){
if ($command->tactics == Crontab::EXECUTE_IMMEDIATELY) {
$executeAbleCommands[] = $command;
$command->tactics = Crontab::EXECUTE_NORMAL;
return $command->save();
}
$can = date('Y-m-d H:i',
(new CronExpression(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) {
$command->tactics = Crontab::DISABLE;
$command->save();
}
$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)
{
new CronExpression($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)
{
new CronExpression($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,42 @@
<?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_NORMAL = 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', $this->aliasField('status'), $this->aliasField('id'), $this->aliasField('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
}

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