正在显示
27 个修改的文件
包含
4793 行增加
和
0 行删除
.gitignore
0 → 100644
CONTRIBUTING.md
0 → 100644
LICENSE.txt
0 → 100644
1 | +ThinkCMF遵循Apache2开源协议发布,并提供免费使用。 | ||
2 | +版权所有Copyright © 2013-2018 by ThinkCMF (https://www.thinkcmf.com) | ||
3 | +All rights reserved。 | ||
4 | + | ||
5 | +Apache Licence是著名的非盈利开源组织Apache采用的协议。 | ||
6 | +该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, | ||
7 | +允许代码修改,再作为开源或商业软件发布。需要满足 | ||
8 | +的条件: | ||
9 | +1. 需要给代码的用户一份Apache Licence ; | ||
10 | +2. 如果你修改了代码,需要在被修改的文件中说明; | ||
11 | +3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 | ||
12 | +带有原来代码中的协议,商标,专利声明和其他原来作者规 | ||
13 | +定需要包含的说明; | ||
14 | +4. 如果再发布的产品中包含一个Notice文件,则在Notice文 | ||
15 | +件中需要带有本协议内容。你可以在Notice中增加自己的 | ||
16 | +许可,但不可以表现为对Apache Licence构成更改。 | ||
17 | +具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 | ||
18 | + | ||
19 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
20 | +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
21 | +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
22 | +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
23 | +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
24 | +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
25 | +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
26 | +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
27 | +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
28 | +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||
29 | +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
30 | +POSSIBILITY OF SUCH DAMAGE. |
README.md
0 → 100644
1 | +ThinkCMF 5.0.190312 正式版 | ||
2 | +=============== | ||
3 | + | ||
4 | +> ThinkCMF5.1已经发布,如果你是新同学,请学习[ThinkCMF5.1](https://github.com/thinkcmf/thinkcmf/tree/5.1),更清爽,更自由! | ||
5 | + | ||
6 | +### 系列讲座 | ||
7 | +https://www.thinkcmf.com/college.html | ||
8 | + | ||
9 | +### ThinkCMF5主要特性 | ||
10 | +* 基于全新 ThinkPHP5.0开发 | ||
11 | +* 更规范的代码,遵循PSR-2命名规范和PSR-4自动加载规范 | ||
12 | +* 更规范的数据库设计 | ||
13 | +* 前后台完全基于bootstrap3 | ||
14 | +* 增加 api 模块(需单独下载) | ||
15 | +* 支持 composer 管理第三方库 | ||
16 | +* 核心化:独立核心代码包 | ||
17 | +* 应用化:开发者以应用的形式增加项目模模块 | ||
18 | +* 插件化:更强的插件机制,开发者以插件形式扩展功能 | ||
19 | +* 模板化:模板完全傻瓜式,用户无须改动任何代码即可在后台完成模板设计和配置 | ||
20 | +* 增加 URL美化功能,支持别名设置,更简单 | ||
21 | +* 独立的回收站功能,可以管理所有应用临时删除的数据 | ||
22 | +* 统一的资源管理,相同文件只保存一份 | ||
23 | +* 注解式的后台菜单管理功能,方便开发者代码管理后台菜单 | ||
24 | +* 文件存储插件化,默认支持七牛文件存储插件 | ||
25 | +* 模板制作标签化,内置多个cmf标签,方便小白用户 | ||
26 | +* 更人性化的导航标签,可以随意定制 html 结构 | ||
27 | +* 后台首页插件化,用户可以定制的网站后台首页 | ||
28 | + | ||
29 | +### 环境推荐 | ||
30 | +> php5.5+ | ||
31 | + | ||
32 | +> mysql 5.6+ | ||
33 | + | ||
34 | +> 打开rewrite | ||
35 | + | ||
36 | + | ||
37 | +### 最低环境要求 | ||
38 | +> php5.4+ | ||
39 | + | ||
40 | +> mysql 5.5+ (mysql5.1安装时选择utf8编码,不支持表情符) | ||
41 | + | ||
42 | +> 打开rewrite | ||
43 | + | ||
44 | + | ||
45 | +### 运行环境配置教程 | ||
46 | +https://www.thinkcmf.com/topic/1502.html | ||
47 | + | ||
48 | + | ||
49 | +### 自动安装 | ||
50 | +> 之前安装过 cmf5的同学,请手动创建`data/install.lock`文件 | ||
51 | + | ||
52 | +代码已经加入自动安装程序,如果你在安装中有任何问题请提交 issue! | ||
53 | + | ||
54 | +1. public目录做为网站根目录,入口文件在 public/index.php | ||
55 | +2. 配置好网站,请访问http://你的域名 | ||
56 | + | ||
57 | +enjoy your cmf~! | ||
58 | + | ||
59 | +### 系统更新 | ||
60 | +如果您是已经安装过 cmf5的用户,请查看 update 目录下的 sql 升级文件,根据自己的下载的程序版本进行更新 | ||
61 | + | ||
62 | +### API开发 (支持app,小程序,web) | ||
63 | +如果你需要 `api` 开发请下载: | ||
64 | +ThinkCMF5 API :https://github.com/thinkcmf/thinkcmfapi | ||
65 | + | ||
66 | +### 完整版目录结构 | ||
67 | +``` | ||
68 | +thinkcmf 根目录 | ||
69 | +├─api api目录(核心版不带) | ||
70 | +├─app 应用目录 | ||
71 | +│ ├─portal 门户应用目录 | ||
72 | +│ │ ├─config.php 应用配置文件 | ||
73 | +│ │ ├─common.php 模块函数文件 | ||
74 | +│ │ ├─controller 控制器目录 | ||
75 | +│ │ ├─model 模型目录 | ||
76 | +│ │ └─ ... 更多类库目录 | ||
77 | +│ ├─ ... 更多应用 | ||
78 | +│ ├─command.php 命令行工具配置文件 | ||
79 | +│ ├─common.php 应用公共(函数)文件 | ||
80 | +│ ├─config.php 应用(公共)配置文件 | ||
81 | +│ ├─database.php 数据库配置文件 | ||
82 | +│ ├─tags.php 应用行为扩展定义文件 | ||
83 | +│ └─route.php 路由配置文件 | ||
84 | +├─data 数据目录 | ||
85 | +│ ├─conf 动态配置目录 | ||
86 | +│ ├─runtime 应用的运行时目录(可写) | ||
87 | +│ └─ ... 更多 | ||
88 | +├─public WEB 部署目录(对外访问目录) | ||
89 | +│ ├─api api入口目录(核心版不带) | ||
90 | +│ ├─plugins 插件目录 | ||
91 | +│ ├─static 静态资源存放目录(css,js,image) | ||
92 | +│ ├─themes 前后台主题目录 | ||
93 | +│ │ ├─admin_simpleboot3 后台默认主题 | ||
94 | +│ │ └─simpleboot3 前台默认主题 | ||
95 | +│ ├─upload 文件上传目录 | ||
96 | +│ ├─index.php 入口文件 | ||
97 | +│ ├─robots.txt 爬虫协议文件 | ||
98 | +│ ├─router.php 快速测试文件 | ||
99 | +│ └─.htaccess apache重写文件 | ||
100 | +├─simplewind | ||
101 | +│ ├─cmf CMF核心库目录 | ||
102 | +│ ├─extend 扩展类库目录 | ||
103 | +│ ├─thinkphp thinkphp目录 | ||
104 | +│ └─vendor 第三方类库目录(Composer) | ||
105 | +├─composer.json composer 定义文件 | ||
106 | +├─LICENSE.txt 授权说明文件 | ||
107 | +├─README.md README 文件 | ||
108 | +├─think 命令行入口文件 | ||
109 | +``` | ||
110 | + | ||
111 | +### 开发手册 | ||
112 | +http://www.kancloud.cn/thinkcmf/doc | ||
113 | + | ||
114 | +### QQ群: | ||
115 | +`ThinkCMF 官方交流群`:316669417 | ||
116 | + | ||
117 | +`ThinkCMF 高级交流群`:100828313 (付费) | ||
118 | +高级群专属权益: | ||
119 | +第一波:两个后台风格(ThinkCMF官网风格后台主题,蓝色风格后台主题) | ||
120 | +第二波:ThinkCMF5完全开发手册离线版(PDF,EPUB,MOBI格式) | ||
121 | +更多专属权益正在路上... | ||
122 | + | ||
123 | +`ThinkCMF 铲屎官交流群`:415136742 (生活娱乐,为有喵的猿人准备) | ||
124 | + | ||
125 | +### 话题专区 | ||
126 | +http://www.thinkcmf.com/topic/index/index/cat/11.html | ||
127 | + | ||
128 | +### 反馈问题 | ||
129 | +https://github.com/thinkcmf/thinkcmf/issues | ||
130 | + | ||
131 | +### 更新日志 | ||
132 | + | ||
133 | +#### 5.0.190419 | ||
134 | +* 优化动态配置函数 | ||
135 | +* 优化门户几处where用法 | ||
136 | +* 优化门户后台表单提交方式 | ||
137 | +* 优化后台菜单url生成 | ||
138 | +* 优化api跨域处理 | ||
139 | +* 修复模板设计公共配置文件有数组时报错 | ||
140 | +* 修复模板设计公共配置文件里数组列表有数据不显示 | ||
141 | + | ||
142 | +#### 5.0.190312 | ||
143 | +* 增加`app,api和插件`composer第三方库支持 | ||
144 | +* 增加插件`@adminMenuRoot`注解 | ||
145 | +* 增加后台模板动态设置 | ||
146 | +* 增加`WEB_ROOT`常量 | ||
147 | +* 优化url美化可能引起的安全漏洞(漏洞编号CVE-2019-6713 感谢topsec(zhan_ran)的及时反馈) | ||
148 | +* 修复api跨域问题 | ||
149 | +* 修复子导航标签报错 | ||
150 | +* 计划删除`PLUGINS_PATH`常量,请不要再使用 | ||
151 | +* 删除`phpoffice/phpspreadsheet`,`phpoffice/phpexcel`,`dompdf/dompdf`第三方库,请自行安装 | ||
152 | +* 移动`qiniu/php-sdk`库到七牛插件 | ||
153 | + | ||
154 | + | ||
155 | +#### 5.0.190111 | ||
156 | +* 升级ThinkPHP到`5.0.24`(包含安全更新) | ||
157 | +* 增加后台模板按文件列表设计 | ||
158 | +* 修复url无法美化 | ||
159 | +* 修复页面数据源报错 | ||
160 | + | ||
161 | +#### 5.0.181231 | ||
162 | +* 规范所有`5.0`代码方便升级到`5.1` | ||
163 | +* 规范控制器`_initialize`方法为`initialize` | ||
164 | +* 调整`cmf_theme_path,cmf_default_theme,cmf_admin_theme_path,cmf_admin_default_theme`到 `template` 配置下 | ||
165 | +* `hook,hook_one`方法取消`$extra`参数 | ||
166 | +* 增加数据库调试模式开关 | ||
167 | +* 增加模板设计关闭功能 | ||
168 | +* 优化七牛下载文件名为上传文件名 | ||
169 | +* 优化清除缓存,清除opcache缓存 | ||
170 | +* 修复七牛获取水印样式报错 | ||
171 | +* 修复模板设计后,前台 js 报错 | ||
172 | + | ||
173 | +#### 5.0.181212 | ||
174 | +* 升级ThinkPHP到`5.0.23`(包含安全更新) | ||
175 | +* 增加`js-bootstrap-year`前端组件 | ||
176 | +* 增加文件大小格式化函数`cmf_file_size_format` | ||
177 | +* 修复网站在二级目录下无法设计模板问题 | ||
178 | +* 修复模板设计公共模板设置数组无法编辑问题 | ||
179 | +* 修复模板设计公共组件数组无法编辑问题 | ||
180 | +* 修复门户模板`page.html`报错 | ||
181 | +* 优化图片验证码生成 | ||
182 | +* 优化`Rest API`跨域问题处理 | ||
183 | + | ||
184 | + | ||
185 | +#### 5.0.180901 | ||
186 | +* 增强模板设计,提供可视化模板设计 | ||
187 | +* 增加模板设计界面钩子 | ||
188 | +* 增加验证码图片钩子 | ||
189 | +* 增加后台设置网站信息界面钩子 | ||
190 | +* 增加后台清除缓存界面钩子 | ||
191 | +* 增加后台导航管理界面钩子 | ||
192 | +* 增加后台友情链接管理界面钩子 | ||
193 | +* 增加后台幻灯片管理界面钩子 | ||
194 | +* 增加后台幻灯片页面列表界面钩子 | ||
195 | +* 增加后台幻灯片页面添加界面钩子 | ||
196 | +* 增加后台幻灯片页面编辑界面钩子 | ||
197 | +* 增加后台管理员列表界面钩子 | ||
198 | +* 增加后台管理员添加界面钩子 | ||
199 | +* 增加后台管理员编辑界面钩子 | ||
200 | +* 增加后台角色管理界面钩子 | ||
201 | +* 增加后台角色添加界面钩子 | ||
202 | +* 增加后台角色编辑界面钩子 | ||
203 | +* 增加后台角色授权界面钩子 | ||
204 | +* 增加用户管理本站用户列表界面钩子 | ||
205 | +* 增加资源管理列表界面钩子 | ||
206 | +* 增加用户管理第三方用户列表界面钩子 | ||
207 | +* 增加后台首页界面钩子 | ||
208 | +* 增加后台回收站界面钩子 | ||
209 | +* 增加后台菜单管理界面钩子 | ||
210 | +* 增加后台自定义登录是否开启钩子 | ||
211 | +* 增加admin.js`js-ajax-btn`组件 | ||
212 | +* 优化插件加载 | ||
213 | +* 优化前后台上传js | ||
214 | + | ||
215 | + | ||
216 | +[门户应用] | ||
217 | +* 增加文章音频,视频功能 | ||
218 | +* 增加门户后台文章管理列表界面钩子 | ||
219 | +* 增加门户后台文章添加界面钩子 | ||
220 | +* 增加门户后台文章编辑界面钩子 | ||
221 | +* 增加门户后台文章分类管理列表界面钩子 | ||
222 | +* 增加门户后台文章分类添加界面钩子 | ||
223 | +* 增加门户后台文章分类编辑界面钩子 | ||
224 | +* 增加门户后台页面管理列表界面钩子 | ||
225 | +* 增加门户后台页面添加界面钩子 | ||
226 | +* 增加门户后台页面编辑界面钩子 | ||
227 | +* 增加门户后台文章标签管理列表界面钩子 | ||
228 | +* 增加门户后台文章添加编辑界面右侧栏钩子 | ||
229 | +* 增加门户后台文章添加编辑界面主要内容钩子 | ||
230 | +* 增加后台文章分类显示隐藏功能 | ||
231 | +* 增加后台文章分类列表搜索功能 | ||
232 | +* 增加后台文章分类列表层级折叠功能 | ||
233 | + | ||
234 | +#### 5.0.180626 | ||
235 | +* 升级TP到`5.0.20` | ||
236 | +* 增加插件REST api基类`PluginRestBaseController` | ||
237 | +* 增加我的喜欢功能 | ||
238 | +* 增加手机相关设备类型判断函数 | ||
239 | +* 优化百度编辑器视频上传 | ||
240 | +* 优化get_client_ip()方法,默认使用高级模式 | ||
241 | +* 优化手机号检查支持国际手机号 | ||
242 | +* 优化图片和文件链接转化函数 | ||
243 | +* Restful api基类增加apiVersion属性 | ||
244 | +* 修复邮箱验证码发送失败 | ||
245 | +* 七牛插件增加东南亚节点 | ||
246 | +* 前台模板文件解析标准化 | ||
247 | + | ||
248 | +[门户应用] | ||
249 | +* 增加文章`thumbnail`字段 | ||
250 | +* 增加文章收藏数功能 | ||
251 | + | ||
252 | +#### 5.0.180525 | ||
253 | +* 修复ajax请求普通页面时返回格式为json | ||
254 | +* 优化图片链接生成 | ||
255 | +* 修复插件模板常量地址问题 | ||
256 | +* 修复后台用户注册验证开关错误 #481 | ||
257 | +* 增加后台刷新后保持当前页面的功能 #475 | ||
258 | +* 取消用户名注册和绑定功能 | ||
259 | +* 优化无限滚动jquery插件 | ||
260 | + | ||
261 | +#### 5.0.180508 | ||
262 | +* 修复用户注册问题 | ||
263 | +* 优化缓存清理,防止删除日志文件 | ||
264 | + | ||
265 | +#### 5.0.180501 | ||
266 | +[核心] | ||
267 | +* 升级TP到5.0.19,增强安全性 | ||
268 | +* 修复模板设计数组编辑验证规则不生效 #440 | ||
269 | +* 修复后台登录失效后iframe里加载首页 | ||
270 | +* 修复七牛插件上传云存储文件没有后缀名问题#437 | ||
271 | +* 修复删除评论时的错误文案提示 #443 | ||
272 | +* 修复ueditor漏洞#431 | ||
273 | +* 修复PHP7.2下后台清除报错 | ||
274 | +* 修复前台账号绑定无法获取mobile、email验证码 #418 | ||
275 | +* 修复百度编辑器大附件上传问题 | ||
276 | +* 修复百度编辑器大视频文件上传问题 | ||
277 | +* 升级font awesome到4.7.0 | ||
278 | + | ||
279 | +[门户应用] | ||
280 | +* 修复文章分类修改层级后子分类层级不更新问题 | ||
281 | +* 优化 portal:articles 标签field,order 属性支持 php 变量 | ||
282 | +* 修复文章分类别名设置为纯数字,路由生成错误,无法访问。 #438 | ||
283 | +* 增加页面相册和附件功能 #449 | ||
284 | + | ||
285 | +#### 5.0.180123 | ||
286 | +[核心] | ||
287 | +* 增加小程序管理插件 | ||
288 | +* 增加插件后台首页左侧菜单显示 | ||
289 | +* 增加 themes 根命名空间 | ||
290 | +* 增加模板设计图片模板变量取消功能 | ||
291 | +* 增加插件自定义处理配置功能 | ||
292 | +* 增加插件后台权限管理功能 | ||
293 | +* 增加后台模板切换 | ||
294 | +* 增加直传云存储功能 | ||
295 | +* 增强导航和子导航标签,自定义更随意 | ||
296 | +* 增加before_content,fetch_upload_view,log_write_done,switch_admin_theme钩子 | ||
297 | +* 增加PluginAdminBaseController基类 | ||
298 | +* 增加系统钩子同步 | ||
299 | +* 增加插件中可使用$site_info变量 | ||
300 | +* 增加 xml 生成函数 | ||
301 | +* 增加插件设置上传文件组件 | ||
302 | +* 优化数字验证码日志写入增加过期时间配置 | ||
303 | +* 优化数字验证码逻辑,增加数字验证码发送图片验证码,【升级时注意界面逻辑】 | ||
304 | +* 优化验证码生成功能,可增加验证码插件管理验证码生成 | ||
305 | +* 优化钩子插件管理 | ||
306 | +* 优化插件注册机制 | ||
307 | +* 优化后台首页菜单加载 | ||
308 | +* 修复模板管理变量数据为array时删除出错 #392 | ||
309 | +* 修复后台管理搜索翻页时条件丢失问题 #366 | ||
310 | +* 修复删除第三方用户时报错 #368 | ||
311 | +* 修复在使用cdn加速js时后台文章编辑器时无法加载编辑器配置 | ||
312 | +* 修复模板设计模板变量file类型不支持上传 #136 | ||
313 | +* 修复用户行为周期设置无效 #382 | ||
314 | +* 修复个人信息编辑签名验证问题 | ||
315 | +* 修复用户生日早于1970年报错 | ||
316 | +* 修复地址坐标选择搜索后无法确定坐标问题 | ||
317 | +* 优化IE8,9下的兼容问题 | ||
318 | +* 优化前台未登录时跳转方式 | ||
319 | + | ||
320 | +[安装程序] | ||
321 | +* 增加安装时管理员密码长度限制 #334 | ||
322 | +* 增加安装时检查 rewrite设置 | ||
323 | +* 增加安装时 innodb 检测 | ||
324 | +* 更正PHP版本要求 | ||
325 | + | ||
326 | +[门户应用] | ||
327 | +* 优化portal:articles标签可在模板里设置分页参数和样式 | ||
328 | +* 优化portal:articles标签所有属性都支持PHP变量 | ||
329 | +* 优化标签控制器支持标签名 | ||
330 | +* 增加portal:tagArticles标签 | ||
331 | +* 取消文章列表用户关联查询 | ||
332 | +* 修复文章多分类进文章列表文章重复问题 | ||
333 | + | ||
334 | + | ||
335 | +#### 5.0.170927 | ||
336 | +[核心] | ||
337 | +* 增加是否开放注册设置 | ||
338 | +* 增加已经安装模板文件检测是否已经删除功能 | ||
339 | +* 增加模板卸载风险提示 | ||
340 | +* 增加钩子同步功能 | ||
341 | +* 增加用户操作同步功能 #291 | ||
342 | +* 增加网站信息【$site_info】变量,可以在插件中使用 #310 | ||
343 | +* 修复添加管理员不能登录 #110 | ||
344 | +* 优化 admin.js | ||
345 | +* 优化后台模板设计排版 | ||
346 | +* 优化后台加密码设置 | ||
347 | +* 返回按钮统一优化 | ||
348 | +* 优化 url 美化时规划选择 | ||
349 | +* 修复`api`模块缺少函数报错 | ||
350 | +* 修复回收站还原提示错误 #111 | ||
351 | +* 修复原始网址和显示网址同时有参数的情况下,两个参数值相同的时候不能解析URL | ||
352 | +* 修复模板设计数组编辑功能缺失 | ||
353 | +* 修复后台登录在双核浏览器下会使用 IE 内核问题#168 | ||
354 | +* 修复模板widget只有数组时,后台设计保存时报错 | ||
355 | +* 修复日期选择在windows firefox下报错 | ||
356 | +* 修复模板设计数据源页面清空链接错误 | ||
357 | +* 修复后台模板设计,json文件中的数组数据,不能正常显示 #222 | ||
358 | +* 修复`cmf\lib\Auth\check`方法逻辑问题 #252 | ||
359 | +* 修复后台用户登录自动退出后iframe页跳转到首页的问题 | ||
360 | +* 修复用户个人资料修改问题 | ||
361 | +* 修复绑定手机号和绑定邮箱号惟一性提示信息错 | ||
362 | + | ||
363 | +[安装程序] | ||
364 | +* 更改安装时数据库默认为127.0.0.1 | ||
365 | +* 优化安装时链接生成 | ||
366 | + | ||
367 | +[门户应用] | ||
368 | +* 增加前台文章控制器默认分类指定 | ||
369 | +* 增加后台文章列表所在分类列 | ||
370 | +* 增加后台文章分类必须指定分类验证 | ||
371 | +* 增加 portal:articles 标签 limit可以设置变量 | ||
372 | +* 增加模板设计页面数据源 | ||
373 | +* 完善 ApiService获取指定分类下的所有子分类方法 | ||
374 | +* 增加portal:categories,portal:subCategories,portal:allSubCategories标签 | ||
375 | +* 增加文章、页面、分类模板选择时模板文件名称查看 | ||
376 | +* 增加文章保存钩子 | ||
377 | +* 优化指定分类下所有子分类获取方法 | ||
378 | +* 修复文章分类管理中不保存选择的模板 #107 | ||
379 | +* 修复面包屑标签 self属性无法识别 false | ||
380 | +* 修复后台编辑文件会覆盖原作者ID #175 | ||
381 | +* 修复后台文章保存后排序变化问题 | ||
382 | +* 修复添加文章分类时 path 没数据问题 | ||
383 | + | ||
384 | +[升级指导] | ||
385 | +https://www.kancloud.cn/thinkcmf/doc/327443 | ||
386 | + | ||
387 | +#### 5.0.170607 | ||
388 | +[核心] | ||
389 | +* 删除 app/common.php | ||
390 | +* 规范 admin.js frontend.js函数名 | ||
391 | +* 更改后台模板设计的模板文件列表排序规则为从小到大排序 | ||
392 | +* 增加模板切换钩子,方便开发者实现复杂的模板切换功能 | ||
393 | +* 增加插件作者和演示信息 | ||
394 | +* 增加数字验证码模板编辑功能 | ||
395 | +* 增加模板变量编辑控件color | ||
396 | +* 增加插件配置组件时间,图片,地理位置,颜色 | ||
397 | +* 优化模板配置更新 | ||
398 | +* 优化文件上传,检查已经上传文件是否存在,不存在重新上传 | ||
399 | +* 修复插件增加新配置时报错 | ||
400 | +* 修复模板变量 rule 规则存在,但没有规则时模板设计保存会报错 | ||
401 | +* 修复后台清除缓存后url生成不美化 | ||
402 | +* 修复模板设计一个页面有多个数组编辑问题 | ||
403 | +* 修复cdn设置不生效 | ||
404 | +* 修复后台菜单添加子菜单不选择上级问题 | ||
405 | +* 修复后台可能多个滚动条 | ||
406 | +* 修复后台添加、编辑角色一处文字错误 | ||
407 | +* 修复插件更新时不更新新增的钩子 | ||
408 | + | ||
409 | +[门户应用] | ||
410 | +* 完善前台模板钩子 | ||
411 | +* 完善文章标签功能 | ||
412 | +* 增加前台模板手机注册关闭开关 | ||
413 | +* 优化文章后台文章分类链接生成 | ||
414 | +* 修复ff下文章相册图片替换和删除问题 | ||
415 | +* 修复文章分类排序功能 | ||
416 | + | ||
417 | +#### 5.0.170520 | ||
418 | +[核心] | ||
419 | +* 完善插件后台管理 | ||
420 | +* 后台登录插件化 | ||
421 | +* 后台首页插件化 | ||
422 | +* 文件存储插件化 | ||
423 | +* 增加 URL 美化功能 | ||
424 | +* 增加后台加密码功能 | ||
425 | +* 增加用户修改头像 | ||
426 | +* 增加插件设置表单验证 | ||
427 | +* 增加前台后台通用语言包 | ||
428 | +* 增加编辑器里上传文件链接替换 | ||
429 | +* 增加应用 command.php 配置文件 | ||
430 | +* 增加后台管理员添加编辑用户名,邮箱惟一性验证 | ||
431 | +* 优化安装程序 | ||
432 | +* 优化上传文件 | ||
433 | +* 优化后台首页 | ||
434 | +* 优化回收站 | ||
435 | +* 优化插件启用禁用 | ||
436 | +* 优化小屏下后台首页不兼容问题 | ||
437 | +* 优化后台图片查看 | ||
438 | +* 修复后台菜单编辑不生效 | ||
439 | +* 修复幻灯片添加不显示问题 | ||
440 | +* 修复导航数据源数据返回为空时报错 | ||
441 | +* 修复 pathinfo 模式下后台本站用户默认头像不显示问题 | ||
442 | +* 修复后台 cdn 不能设置 | ||
443 | +* 合并asset应用到 user | ||
444 | + | ||
445 | +[门户应用] | ||
446 | +* 增加文章收藏功能 | ||
447 | +* 增加文章点赞限制,一个用户只能点赞一次 | ||
448 | +* 增加文章分类缩略图 | ||
449 | +* 优化文章分类管理删除 | ||
450 | +* 优化文章页和页面页内容图片样式问题 | ||
451 | +* 修复文章添加编辑默认图片错误 | ||
452 | +* 修复分类下没有文章时报错 | ||
453 | +* 修复页面模板设置无效 | ||
454 | +* 修复页面删除后仍可以访问 | ||
455 | + | ||
456 | +#### 5.0.170505 | ||
457 | +[核心] | ||
458 | +* 完善用户注册流程 | ||
459 | +* 完善插件功能 | ||
460 | +* 增加手机验证码发送钩子 | ||
461 | +* 增加手机验证码发送演示插件 | ||
462 | +* 增加用户邮箱绑定 | ||
463 | +* 增加用户手机绑定 | ||
464 | +* 增加常用模板钩子 | ||
465 | +* 增加模板设计图片上传 | ||
466 | +* 增加用户密码修改 | ||
467 | +* 增加用户收藏功能 | ||
468 | +* 增加导航标签,子导航标签增加 `max-level` 设置 | ||
469 | +* 修复邮箱验证码发送 | ||
470 | +* 修复windows下获取模板数据时模板文件路径问题 | ||
471 | +* 修复单文件,多文件上传 | ||
472 | +* 修复后台首页用户昵称一直显示admin | ||
473 | +* 修复 `navigation`,`subNavigation` 标签两个以上不能同时使用问题 | ||
474 | +* 修复 console 模式报错 | ||
475 | +* 取消前台有错误时界面刷新 | ||
476 | + | ||
477 | +[门户应用] | ||
478 | +* 增加文章附件功能 | ||
479 | +* 优化文章相册 | ||
480 | + | ||
481 | +#### 5.0.170422 | ||
482 | +[核心] | ||
483 | +* 完善幻灯片 | ||
484 | +* 完善后台控制器方法注释 | ||
485 | +* 增加调试模式下实时更新模板配置 | ||
486 | +* 增加友情链接图片上传 | ||
487 | +* 增加应用公共语言包功能 | ||
488 | +* 增加资源管理 | ||
489 | +* 增加模板设计数据源层级关系 | ||
490 | +* 更新jQuery Form版本 | ||
491 | +* 增加后台菜单类型是否有界面区分 | ||
492 | +* 增加权限验证时权限规则里没有的规则不用验证 | ||
493 | +* 增加前台网站信息获取 | ||
494 | +* 优化后台菜单导入 | ||
495 | +* 统一排序规则,按从小到大排序 | ||
496 | +* 修复后台模板管理点更新提示卸载 | ||
497 | +* 修复标签`NavigationMenu` | ||
498 | +* 修复菜单导入时未添加权限规则 | ||
499 | +* 修复`navigationFolder`设置多个子菜单后会多循环数据 | ||
500 | +* 修复部分代码php5.4下不兼容 | ||
501 | +* 修复后台菜单不能添加编辑 | ||
502 | + | ||
503 | +[门户应用] | ||
504 | +* 完全独立门户应用 | ||
505 | +* 完善后台页面管理 | ||
506 | +* 完善面包屑标签`breadcrumb` | ||
507 | +* 完善文章分类管理 | ||
508 | +* 完善文章管理 | ||
509 | +* 修复文章分类`path`更新 | ||
510 | +* 优化文章列表标签`articles` | ||
511 | +* 优化后台文章分类选择 | ||
512 | +* 增加前台文章点赞功能 | ||
513 | +* 增加前台文章搜索功能 | ||
514 | +* 增加文章列表分页总数获取 | ||
515 | + | ||
516 | +#### 5.0.170401 | ||
517 | +* 完善文件上传 | ||
518 | +* 增加回收站功能 | ||
519 | +* 完善友情链接 | ||
520 | +* 优化网站设置 | ||
521 | +* 增加后台登陆验证码 | ||
522 | +* 修复后台用户密码修改 | ||
523 | +* 修复用户管理-本站用户头像不显示 | ||
524 | +* 完善前台用户登录注册 | ||
525 | +* 增加后台菜单导入 | ||
526 | +* 修复后台菜单列表排序 | ||
527 | +* 完善导航 | ||
528 | +* 增加插件钩子管理 | ||
529 | +* 完善前台模板 | ||
530 | + | ||
531 | + |
_config.yml
0 → 100644
1 | +theme: jekyll-theme-cayman |
app/admin/annotation/AdminMenuAnnotation.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <zxxjjforever@163.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\annotation; | ||
12 | + | ||
13 | +use mindplay\annotations\Annotation; | ||
14 | + | ||
15 | +/** | ||
16 | + * Specifies validation of a string, requiring a minimum and/or maximum length. | ||
17 | + * | ||
18 | + * @usage('method'=>true, 'inherited'=>true, 'multiple'=>false) | ||
19 | + */ | ||
20 | +class AdminMenuAnnotation extends Annotation | ||
21 | +{ | ||
22 | + public $remark = ''; | ||
23 | + | ||
24 | + public $icon = ''; | ||
25 | + | ||
26 | + public $name = ''; | ||
27 | + | ||
28 | + public $param = ''; | ||
29 | + | ||
30 | + public $parent = ''; | ||
31 | + | ||
32 | + public $display = false; | ||
33 | + | ||
34 | + public $order = 10000; | ||
35 | + | ||
36 | + public $hasView = true; | ||
37 | + | ||
38 | + /** | ||
39 | + * Initialize the annotation. | ||
40 | + * @param array $properties | ||
41 | + */ | ||
42 | + public function initAnnotation(array $properties) | ||
43 | + { | ||
44 | + parent::initAnnotation($properties); | ||
45 | + } | ||
46 | +} |
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <zxxjjforever@163.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\annotation; | ||
12 | + | ||
13 | +use mindplay\annotations\AnnotationException; | ||
14 | +use mindplay\annotations\Annotation; | ||
15 | + | ||
16 | +/** | ||
17 | + * Specifies validation of a string, requiring a minimum and/or maximum length. | ||
18 | + * | ||
19 | + * @usage('class'=>true, 'inherited'=>true, 'multiple'=>true) | ||
20 | + */ | ||
21 | +class AdminMenuRootAnnotation extends Annotation | ||
22 | +{ | ||
23 | + /** | ||
24 | + * @var int|null Minimum string length (or null, if no minimum) | ||
25 | + */ | ||
26 | + public $remark = ''; | ||
27 | + | ||
28 | + /** | ||
29 | + * @var int|null Maximum string length (or null, if no maximum) | ||
30 | + */ | ||
31 | + public $icon = ''; | ||
32 | + | ||
33 | + /** | ||
34 | + * @var int|null Minimum string length (or null, if no minimum) | ||
35 | + */ | ||
36 | + public $name = ''; | ||
37 | + | ||
38 | + public $action = ''; | ||
39 | + | ||
40 | + public $param = ''; | ||
41 | + | ||
42 | + public $parent = ''; | ||
43 | + | ||
44 | + public $display = false; | ||
45 | + | ||
46 | + public $order = 10000; | ||
47 | + | ||
48 | + /** | ||
49 | + * Initialize the annotation. | ||
50 | + * @param array $properties | ||
51 | + */ | ||
52 | + public function initAnnotation(array $properties) | ||
53 | + { | ||
54 | + parent::initAnnotation($properties); | ||
55 | + } | ||
56 | +} |
app/admin/api/NavApi.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <thinkcmf@126.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\api; | ||
12 | + | ||
13 | +use app\admin\model\NavModel; | ||
14 | +use think\db\Query; | ||
15 | + | ||
16 | +class NavApi | ||
17 | +{ | ||
18 | + /** | ||
19 | + * 导航模板数据源 用于模板设计 | ||
20 | + * @param array $param | ||
21 | + * @return array|\PDOStatement|string|\think\Collection | ||
22 | + * @throws \think\db\exception\DataNotFoundException | ||
23 | + * @throws \think\db\exception\ModelNotFoundException | ||
24 | + * @throws \think\exception\DbException | ||
25 | + */ | ||
26 | + public function index($param = []) | ||
27 | + { | ||
28 | + $navModel = new NavModel(); | ||
29 | + | ||
30 | + $result = $navModel | ||
31 | + ->where(function (Query $query) use ($param) { | ||
32 | + if (!empty($param['keyword'])) { | ||
33 | + $query->where('name', 'like', "%{$param['keyword']}%"); | ||
34 | + } | ||
35 | + })->select(); | ||
36 | + | ||
37 | + return $result; | ||
38 | + } | ||
39 | + | ||
40 | +} |
app/admin/api/NavMenuApi.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <thinkcmf@126.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\api; | ||
12 | + | ||
13 | +use app\admin\model\NavMenuModel; | ||
14 | + | ||
15 | +class NavMenuApi | ||
16 | +{ | ||
17 | + /** | ||
18 | + * 导航菜单模板数据源 用于模板设计 | ||
19 | + * @param array $param | ||
20 | + * @return array|\PDOStatement|string|\think\Collection | ||
21 | + * @throws \think\db\exception\DataNotFoundException | ||
22 | + * @throws \think\db\exception\ModelNotFoundException | ||
23 | + * @throws \think\exception\DbException | ||
24 | + */ | ||
25 | + public function index($param = []) | ||
26 | + { | ||
27 | + $navMenuModel = new NavMenuModel(); | ||
28 | + | ||
29 | + $result = $navMenuModel | ||
30 | + ->where(function (Query $query) use ($param) { | ||
31 | + if (!empty($param['keyword'])) { | ||
32 | + $query->where('name', 'like', "%{$param['keyword']}%"); | ||
33 | + } | ||
34 | + | ||
35 | + if (!empty($param['id'])) { | ||
36 | + $query->where('nav_id', intval($param['id'])); | ||
37 | + } | ||
38 | + })->select(); | ||
39 | + | ||
40 | + return $result; | ||
41 | + } | ||
42 | + | ||
43 | +} |
app/admin/api/SlideApi.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <thinkcmf@126.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\api; | ||
12 | + | ||
13 | +use app\admin\model\SlideModel; | ||
14 | +use think\db\Query; | ||
15 | + | ||
16 | +class SlideApi | ||
17 | +{ | ||
18 | + /** | ||
19 | + * 幻灯片模板数据源 用于模板设计 | ||
20 | + * @param array $param | ||
21 | + * @return false|\PDOStatement|string|\think\Collection | ||
22 | + * @throws \think\db\exception\DataNotFoundException | ||
23 | + * @throws \think\db\exception\ModelNotFoundException | ||
24 | + * @throws \think\exception\DbException | ||
25 | + */ | ||
26 | + public function index($param = []) | ||
27 | + { | ||
28 | + $slideModel = new SlideModel(); | ||
29 | + | ||
30 | + //返回的数据必须是数据集或数组,item里必须包括id,name,如果想表示层级关系请加上 parent_id | ||
31 | + return $slideModel | ||
32 | + ->where(function (Query $query) use ($param) { | ||
33 | + if (!empty($param['keyword'])) { | ||
34 | + $query->where('name', 'like', "%{$param['keyword']}%"); | ||
35 | + } | ||
36 | + })->select(); | ||
37 | + } | ||
38 | + | ||
39 | +} |
app/admin/controller/AboutUsController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use app\admin\model\AboutUsModel; | ||
15 | +use app\portal\model\PortalPostModel; | ||
16 | + | ||
17 | +class AboutUsController extends AdminBaseController | ||
18 | +{ | ||
19 | + protected $targets = ["_blank" => "新标签页打开", "_self" => "本窗口打开"]; | ||
20 | + | ||
21 | + //编辑页面 | ||
22 | + public function edit(){ | ||
23 | + $AboutUsModel = new AboutUsModel(); | ||
24 | + $about = $AboutUsModel->where('id',1)->find(); | ||
25 | + $contentModel = new PortalPostModel(); | ||
26 | + $about['content'] = $contentModel->getPostContentAttr($about['content']); | ||
27 | + $this->assign('post', $about); | ||
28 | + return $this->fetch(); | ||
29 | + } | ||
30 | + | ||
31 | + //编辑保存页面 | ||
32 | + public function editPost(){ | ||
33 | + $data = $this->request->param(); | ||
34 | + $AboutUsModel = new AboutUsModel(); | ||
35 | + $result = $this->validate($data, 'AboutUs'); | ||
36 | + if ($result !== true) { | ||
37 | + $this->error($result); | ||
38 | + } | ||
39 | + $contentModel = new PortalPostModel(); | ||
40 | + $data['content'] = $contentModel->setPostContentAttr($data['content']); | ||
41 | + $AboutUsModel->allowField(true)->isUpdate(true)->save($data); | ||
42 | + | ||
43 | + $this->success("保存成功!"); | ||
44 | + } | ||
45 | +} |
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use app\admin\model\CooperationModel; | ||
15 | + | ||
16 | +class CooperationController extends AdminBaseController | ||
17 | +{ | ||
18 | + protected $targets = ["_blank" => "新标签页打开", "_self" => "本窗口打开"]; | ||
19 | + | ||
20 | + //首页 | ||
21 | + public function index(){ | ||
22 | + $CooperationModel = new CooperationModel(); | ||
23 | + $cooperation = $CooperationModel->order('weigh desc')->select(); | ||
24 | + $this->assign('cooperation', $cooperation); | ||
25 | + return $this->fetch(); | ||
26 | + } | ||
27 | + | ||
28 | + //添加页面 | ||
29 | + public function add(){ | ||
30 | + $this->assign('targets', $this->targets); | ||
31 | + return $this->fetch(); | ||
32 | + } | ||
33 | + | ||
34 | + //提交保存 | ||
35 | + public function addPost(){ | ||
36 | + $data = $this->request->param(); | ||
37 | + $CooperationModel = new CooperationModel(); | ||
38 | + $result = $this->validate($data, 'Cooperation'); | ||
39 | + if ($result !== true) { | ||
40 | + $this->error($result); | ||
41 | + } | ||
42 | + $CooperationModel->allowField(true)->save($data); | ||
43 | + | ||
44 | + $this->success("添加成功!", url("Cooperation/index")); | ||
45 | + } | ||
46 | + | ||
47 | + //编辑页面 | ||
48 | + public function edit(){ | ||
49 | + $id = $this->request->param('id', 0, 'intval'); | ||
50 | + $CooperationModel = new CooperationModel(); | ||
51 | + $cooperation = $CooperationModel->get($id); | ||
52 | + $this->assign('targets', $this->targets); | ||
53 | + $this->assign('cooperation', $cooperation); | ||
54 | + return $this->fetch(); | ||
55 | + } | ||
56 | + | ||
57 | + //编辑保存页面 | ||
58 | + public function editPost() | ||
59 | + { | ||
60 | + $data = $this->request->param(); | ||
61 | + $CooperationModel = new CooperationModel(); | ||
62 | + $result = $this->validate($data, 'Cooperation'); | ||
63 | + if ($result !== true) { | ||
64 | + $this->error($result); | ||
65 | + } | ||
66 | + $CooperationModel->allowField(true)->isUpdate(true)->save($data); | ||
67 | + | ||
68 | + $this->success("保存成功!", url("Cooperation/index")); | ||
69 | + } | ||
70 | + | ||
71 | + //删除 | ||
72 | + public function delete(){ | ||
73 | + $id = $this->request->param('id', 0, 'intval'); | ||
74 | + CooperationModel::destroy($id); | ||
75 | + $this->success("删除成功!", url("Cooperation/index")); | ||
76 | + } | ||
77 | + | ||
78 | + //显示与隐藏 | ||
79 | + public function toggle() | ||
80 | + { | ||
81 | + $data = $this->request->param(); | ||
82 | + $CooperationModel = new CooperationModel(); | ||
83 | + | ||
84 | + if (isset($data['ids']) && !empty($data["display"])) { | ||
85 | + $ids = $this->request->param('ids/a'); | ||
86 | + $CooperationModel->where('id', 'in', $ids)->update(['status' => 1]); | ||
87 | + $this->success("更新成功!"); | ||
88 | + } | ||
89 | + | ||
90 | + if (isset($data['ids']) && !empty($data["hide"])) { | ||
91 | + $ids = $this->request->param('ids/a'); | ||
92 | + $CooperationModel->where('id', 'in', $ids)->update(['status' => 0]); | ||
93 | + $this->success("更新成功!"); | ||
94 | + } | ||
95 | + | ||
96 | + } | ||
97 | + | ||
98 | +} |
app/admin/controller/DialogController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <zxxjjforever@163.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | + | ||
15 | +class DialogController extends AdminBaseController | ||
16 | +{ | ||
17 | + public function initialize() | ||
18 | + { | ||
19 | + | ||
20 | + } | ||
21 | + | ||
22 | + public function map() | ||
23 | + { | ||
24 | + $location = $this->request->param('location'); | ||
25 | + $location = explode(',', $location); | ||
26 | + $lng = empty($location[0]) ? 116.424966 : $location[0]; | ||
27 | + $lat = empty($location[1]) ? 39.907851 : $location[1]; | ||
28 | + | ||
29 | + $this->assign(['lng' => $lng, 'lat' => $lat]); | ||
30 | + return $this->fetch(); | ||
31 | + } | ||
32 | + | ||
33 | +} |
app/admin/controller/FocusController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use app\admin\model\FocusModel; | ||
15 | + | ||
16 | +class FocusController extends AdminBaseController | ||
17 | +{ | ||
18 | + protected $targets = ["_blank" => "新标签页打开", "_self" => "本窗口打开"]; | ||
19 | + | ||
20 | + //首页 | ||
21 | + public function index(){ | ||
22 | + $FocusModel = new FocusModel(); | ||
23 | + $Focus = $FocusModel->order('weigh desc')->select(); | ||
24 | + $this->assign('focus', $Focus); | ||
25 | + return $this->fetch(); | ||
26 | + } | ||
27 | + | ||
28 | + //添加页面 | ||
29 | + public function add(){ | ||
30 | + $this->assign('targets', $this->targets); | ||
31 | + return $this->fetch(); | ||
32 | + } | ||
33 | + | ||
34 | + //提交保存 | ||
35 | + public function addPost(){ | ||
36 | + $data = $this->request->param(); | ||
37 | + $FocusModel = new FocusModel(); | ||
38 | + $result = $this->validate($data, 'Focus'); | ||
39 | + if ($result !== true) { | ||
40 | + $this->error($result); | ||
41 | + } | ||
42 | + $FocusModel->allowField(true)->save($data); | ||
43 | + | ||
44 | + $this->success("添加成功!", url("Focus/index")); | ||
45 | + } | ||
46 | + | ||
47 | + //编辑页面 | ||
48 | + public function edit(){ | ||
49 | + $id = $this->request->param('id', 0, 'intval'); | ||
50 | + $FocusModel = new FocusModel(); | ||
51 | + $Focus = $FocusModel->get($id); | ||
52 | + $this->assign('targets', $this->targets); | ||
53 | + $this->assign('focus', $Focus); | ||
54 | + return $this->fetch(); | ||
55 | + } | ||
56 | + | ||
57 | + //编辑保存页面 | ||
58 | + public function editPost() | ||
59 | + { | ||
60 | + $data = $this->request->param(); | ||
61 | + $FocusModel = new FocusModel(); | ||
62 | + $result = $this->validate($data, 'Focus'); | ||
63 | + if ($result !== true) { | ||
64 | + $this->error($result); | ||
65 | + } | ||
66 | + $FocusModel->allowField(true)->isUpdate(true)->save($data); | ||
67 | + | ||
68 | + $this->success("保存成功!", url("Focus/index")); | ||
69 | + } | ||
70 | + | ||
71 | + //删除 | ||
72 | + public function delete(){ | ||
73 | + $id = $this->request->param('id', 0, 'intval'); | ||
74 | + FocusModel::destroy($id); | ||
75 | + $this->success("删除成功!", url("Focus/index")); | ||
76 | + } | ||
77 | + | ||
78 | + //显示与隐藏 | ||
79 | + public function toggle() | ||
80 | + { | ||
81 | + $data = $this->request->param(); | ||
82 | + $FocusModel = new FocusModel(); | ||
83 | + | ||
84 | + if (isset($data['ids']) && !empty($data["display"])) { | ||
85 | + $ids = $this->request->param('ids/a'); | ||
86 | + $FocusModel->where('id', 'in', $ids)->update(['status' => 1]); | ||
87 | + $this->success("更新成功!"); | ||
88 | + } | ||
89 | + | ||
90 | + if (isset($data['ids']) && !empty($data["hide"])) { | ||
91 | + $ids = $this->request->param('ids/a'); | ||
92 | + $FocusModel->where('id', 'in', $ids)->update(['status' => 0]); | ||
93 | + $this->success("更新成功!"); | ||
94 | + } | ||
95 | + | ||
96 | + } | ||
97 | + | ||
98 | +} |
app/admin/controller/HookController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <zxxjjforever@163.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use app\admin\model\HookModel; | ||
15 | +use app\admin\model\PluginModel; | ||
16 | +use app\admin\model\HookPluginModel; | ||
17 | +use think\Db; | ||
18 | + | ||
19 | +/** | ||
20 | + * Class HookController 钩子管理控制器 | ||
21 | + * @package app\admin\controller | ||
22 | + */ | ||
23 | +class HookController extends AdminBaseController | ||
24 | +{ | ||
25 | + /** | ||
26 | + * 钩子管理 | ||
27 | + * @adminMenu( | ||
28 | + * 'name' => '钩子管理', | ||
29 | + * 'parent' => 'admin/Plugin/default', | ||
30 | + * 'display'=> true, | ||
31 | + * 'hasView'=> true, | ||
32 | + * 'order' => 10000, | ||
33 | + * 'icon' => '', | ||
34 | + * 'remark' => '钩子管理', | ||
35 | + * 'param' => '' | ||
36 | + * ) | ||
37 | + */ | ||
38 | + public function index() | ||
39 | + { | ||
40 | + $hookModel = new HookModel(); | ||
41 | + $hooks = $hookModel->select(); | ||
42 | + $this->assign('hooks', $hooks); | ||
43 | + return $this->fetch(); | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * 钩子插件管理 | ||
48 | + * @adminMenu( | ||
49 | + * 'name' => '钩子插件管理', | ||
50 | + * 'parent' => 'index', | ||
51 | + * 'display'=> false, | ||
52 | + * 'hasView'=> true, | ||
53 | + * 'order' => 10000, | ||
54 | + * 'icon' => '', | ||
55 | + * 'remark' => '钩子插件管理', | ||
56 | + * 'param' => '' | ||
57 | + * ) | ||
58 | + */ | ||
59 | + public function plugins() | ||
60 | + { | ||
61 | + $hook = $this->request->param('hook'); | ||
62 | + $pluginModel = new PluginModel(); | ||
63 | + $plugins = $pluginModel | ||
64 | + ->field('a.*,b.hook,b.plugin,b.list_order,b.status as hook_plugin_status,b.id as hook_plugin_id') | ||
65 | + ->alias('a') | ||
66 | + ->join('__HOOK_PLUGIN__ b', 'a.name = b.plugin') | ||
67 | + ->where('b.hook', $hook) | ||
68 | + ->order('b.list_order asc') | ||
69 | + ->select(); | ||
70 | + $this->assign('plugins', $plugins); | ||
71 | + return $this->fetch(); | ||
72 | + } | ||
73 | + | ||
74 | + /** | ||
75 | + * 钩子插件排序 | ||
76 | + * @adminMenu( | ||
77 | + * 'name' => '钩子插件排序', | ||
78 | + * 'parent' => 'index', | ||
79 | + * 'display'=> false, | ||
80 | + * 'hasView'=> false, | ||
81 | + * 'order' => 10000, | ||
82 | + * 'icon' => '', | ||
83 | + * 'remark' => '钩子插件排序', | ||
84 | + * 'param' => '' | ||
85 | + * ) | ||
86 | + */ | ||
87 | + public function pluginListOrder() | ||
88 | + { | ||
89 | + $hookPluginModel = new HookPluginModel(); | ||
90 | + parent::listOrders($hookPluginModel); | ||
91 | + | ||
92 | + $this->success("排序更新成功!"); | ||
93 | + } | ||
94 | + | ||
95 | + /** | ||
96 | + * 同步钩子 | ||
97 | + * @adminMenu( | ||
98 | + * 'name' => '同步钩子', | ||
99 | + * 'parent' => 'index', | ||
100 | + * 'display'=> false, | ||
101 | + * 'hasView'=> true, | ||
102 | + * 'order' => 10000, | ||
103 | + * 'icon' => '', | ||
104 | + * 'remark' => '同步钩子', | ||
105 | + * 'param' => '' | ||
106 | + * ) | ||
107 | + */ | ||
108 | + public function sync() | ||
109 | + { | ||
110 | + | ||
111 | + $apps = cmf_scan_dir(APP_PATH . '*', GLOB_ONLYDIR); | ||
112 | + | ||
113 | + array_push($apps, 'cmf'); | ||
114 | + | ||
115 | + foreach ($apps as $app) { | ||
116 | + if ($app == 'cmf') { | ||
117 | + $hookConfigFile = cmf_core_path() . 'hooks.php'; | ||
118 | + } else { | ||
119 | + $hookConfigFile = APP_PATH . $app . '/hooks.php'; | ||
120 | + } | ||
121 | + | ||
122 | + if (file_exists($hookConfigFile)) { | ||
123 | + $hooksInFile = include $hookConfigFile; | ||
124 | + | ||
125 | + foreach ($hooksInFile as $hookName => $hook) { | ||
126 | + | ||
127 | + $hook['type'] = empty($hook['type']) ? 2 : $hook['type']; | ||
128 | + | ||
129 | + if (!in_array($hook['type'], [2, 3, 4]) && $app != 'cmf') { | ||
130 | + $hook['type'] = 2; | ||
131 | + } | ||
132 | + | ||
133 | + $findHook = Db::name('hook')->where('hook', $hookName)->count(); | ||
134 | + | ||
135 | + $hook['app'] = $app; | ||
136 | + | ||
137 | + if ($findHook > 0) { | ||
138 | + Db::name('hook')->where('hook', $hookName)->strict(false)->field(true)->update($hook); | ||
139 | + } else { | ||
140 | + $hook['hook'] = $hookName; | ||
141 | + Db::name('hook')->insert($hook); | ||
142 | + } | ||
143 | + } | ||
144 | + } | ||
145 | + } | ||
146 | + | ||
147 | + return $this->fetch(); | ||
148 | + } | ||
149 | + | ||
150 | + | ||
151 | +} |
app/admin/controller/IndexController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use think\Db; | ||
15 | +use app\admin\model\AdminMenuModel; | ||
16 | + | ||
17 | +class IndexController extends AdminBaseController | ||
18 | +{ | ||
19 | + | ||
20 | + public function initialize() | ||
21 | + { | ||
22 | + $adminSettings = cmf_get_option('admin_settings'); | ||
23 | + if (empty($adminSettings['admin_password']) || $this->request->path() == $adminSettings['admin_password']) { | ||
24 | + $adminId = cmf_get_current_admin_id(); | ||
25 | + if (empty($adminId)) { | ||
26 | + session("__LOGIN_BY_CMF_ADMIN_PW__", 1);//设置后台登录加密码 | ||
27 | + } | ||
28 | + } | ||
29 | + | ||
30 | + parent::initialize(); | ||
31 | + } | ||
32 | + | ||
33 | + /** | ||
34 | + * 后台首页 | ||
35 | + */ | ||
36 | + public function index() | ||
37 | + { | ||
38 | + $content = hook_one('admin_index_index_view'); | ||
39 | + | ||
40 | + if (!empty($content)) { | ||
41 | + return $content; | ||
42 | + } | ||
43 | + | ||
44 | + $adminMenuModel = new AdminMenuModel(); | ||
45 | + $menus = cache('admin_menus_' . cmf_get_current_admin_id(), '', null, 'admin_menus'); | ||
46 | + | ||
47 | + if (empty($menus)) { | ||
48 | + $menus = $adminMenuModel->menuTree(); | ||
49 | + cache('admin_menus_' . cmf_get_current_admin_id(), $menus, null, 'admin_menus'); | ||
50 | + } | ||
51 | + | ||
52 | + $this->assign("menus", $menus); | ||
53 | + | ||
54 | + | ||
55 | + $result = Db::name('AdminMenu')->order(["app" => "ASC", "controller" => "ASC", "action" => "ASC"])->select(); | ||
56 | + $menusTmp = array(); | ||
57 | + foreach ($result as $item){ | ||
58 | + //去掉/ _ 全部小写。作为索引。 | ||
59 | + $indexTmp = $item['app'].$item['controller'].$item['action']; | ||
60 | + $indexTmp = preg_replace("/[\\/|_]/","",$indexTmp); | ||
61 | + $indexTmp = strtolower($indexTmp); | ||
62 | + $menusTmp[$indexTmp] = $item; | ||
63 | + } | ||
64 | + $this->assign("menus_js_var",json_encode($menusTmp)); | ||
65 | + | ||
66 | + //$admin = Db::name("user")->where('id', cmf_get_current_admin_id())->find(); | ||
67 | + //$this->assign('admin', $admin); | ||
68 | + return $this->fetch(); | ||
69 | + } | ||
70 | +} |
app/admin/controller/LinkController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use app\admin\model\LinkModel; | ||
15 | + | ||
16 | +class LinkController extends AdminBaseController | ||
17 | +{ | ||
18 | + protected $targets = ["_blank" => "新标签页打开", "_self" => "本窗口打开"]; | ||
19 | + | ||
20 | + /** | ||
21 | + * 友情链接管理 | ||
22 | + * @adminMenu( | ||
23 | + * 'name' => '友情链接', | ||
24 | + * 'parent' => 'admin/Setting/default', | ||
25 | + * 'display'=> true, | ||
26 | + * 'hasView'=> true, | ||
27 | + * 'order' => 50, | ||
28 | + * 'icon' => '', | ||
29 | + * 'remark' => '友情链接管理', | ||
30 | + * 'param' => '' | ||
31 | + * ) | ||
32 | + * @return mixed | ||
33 | + * @throws \think\db\exception\DataNotFoundException | ||
34 | + * @throws \think\db\exception\ModelNotFoundException | ||
35 | + * @throws \think\exception\DbException | ||
36 | + */ | ||
37 | + public function index() | ||
38 | + { | ||
39 | + $content = hook_one('admin_link_index_view'); | ||
40 | + | ||
41 | + if (!empty($content)) { | ||
42 | + return $content; | ||
43 | + } | ||
44 | + | ||
45 | + $linkModel = new LinkModel(); | ||
46 | + $links = $linkModel->select(); | ||
47 | + $this->assign('links', $links); | ||
48 | + | ||
49 | + return $this->fetch(); | ||
50 | + } | ||
51 | + | ||
52 | + /** | ||
53 | + * 添加友情链接 | ||
54 | + * @adminMenu( | ||
55 | + * 'name' => '添加友情链接', | ||
56 | + * 'parent' => 'index', | ||
57 | + * 'display'=> false, | ||
58 | + * 'hasView'=> true, | ||
59 | + * 'order' => 10000, | ||
60 | + * 'icon' => '', | ||
61 | + * 'remark' => '添加友情链接', | ||
62 | + * 'param' => '' | ||
63 | + * ) | ||
64 | + */ | ||
65 | + public function add() | ||
66 | + { | ||
67 | + $this->assign('targets', $this->targets); | ||
68 | + return $this->fetch(); | ||
69 | + } | ||
70 | + | ||
71 | + /** | ||
72 | + * 添加友情链接提交保存 | ||
73 | + * @adminMenu( | ||
74 | + * 'name' => '添加友情链接提交保存', | ||
75 | + * 'parent' => 'index', | ||
76 | + * 'display'=> false, | ||
77 | + * 'hasView'=> false, | ||
78 | + * 'order' => 10000, | ||
79 | + * 'icon' => '', | ||
80 | + * 'remark' => '添加友情链接提交保存', | ||
81 | + * 'param' => '' | ||
82 | + * ) | ||
83 | + */ | ||
84 | + public function addPost() | ||
85 | + { | ||
86 | + $data = $this->request->param(); | ||
87 | + $linkModel = new LinkModel(); | ||
88 | + $result = $this->validate($data, 'Link'); | ||
89 | + if ($result !== true) { | ||
90 | + $this->error($result); | ||
91 | + } | ||
92 | + $linkModel->allowField(true)->save($data); | ||
93 | + | ||
94 | + $this->success("添加成功!", url("Link/index")); | ||
95 | + } | ||
96 | + | ||
97 | + /** | ||
98 | + * 编辑友情链接 | ||
99 | + * @adminMenu( | ||
100 | + * 'name' => '编辑友情链接', | ||
101 | + * 'parent' => 'index', | ||
102 | + * 'display'=> false, | ||
103 | + * 'hasView'=> true, | ||
104 | + * 'order' => 10000, | ||
105 | + * 'icon' => '', | ||
106 | + * 'remark' => '编辑友情链接', | ||
107 | + * 'param' => '' | ||
108 | + * ) | ||
109 | + * @return mixed | ||
110 | + * @throws \think\Exception\DbException | ||
111 | + */ | ||
112 | + public function edit() | ||
113 | + { | ||
114 | + $id = $this->request->param('id', 0, 'intval'); | ||
115 | + $linkModel = new LinkModel(); | ||
116 | + $link = $linkModel->get($id); | ||
117 | + $this->assign('targets', $this->targets); | ||
118 | + $this->assign('link', $link); | ||
119 | + return $this->fetch(); | ||
120 | + } | ||
121 | + | ||
122 | + /** | ||
123 | + * 编辑友情链接提交保存 | ||
124 | + * @adminMenu( | ||
125 | + * 'name' => '编辑友情链接提交保存', | ||
126 | + * 'parent' => 'index', | ||
127 | + * 'display'=> false, | ||
128 | + * 'hasView'=> false, | ||
129 | + * 'order' => 10000, | ||
130 | + * 'icon' => '', | ||
131 | + * 'remark' => '编辑友情链接提交保存', | ||
132 | + * 'param' => '' | ||
133 | + * ) | ||
134 | + */ | ||
135 | + public function editPost() | ||
136 | + { | ||
137 | + $data = $this->request->param(); | ||
138 | + $linkModel = new LinkModel(); | ||
139 | + $result = $this->validate($data, 'Link'); | ||
140 | + if ($result !== true) { | ||
141 | + $this->error($result); | ||
142 | + } | ||
143 | + $linkModel->allowField(true)->isUpdate(true)->save($data); | ||
144 | + | ||
145 | + $this->success("保存成功!", url("Link/index")); | ||
146 | + } | ||
147 | + | ||
148 | + /** | ||
149 | + * 删除友情链接 | ||
150 | + * @adminMenu( | ||
151 | + * 'name' => '删除友情链接', | ||
152 | + * 'parent' => 'index', | ||
153 | + * 'display'=> false, | ||
154 | + * 'hasView'=> false, | ||
155 | + * 'order' => 10000, | ||
156 | + * 'icon' => '', | ||
157 | + * 'remark' => '删除友情链接', | ||
158 | + * 'param' => '' | ||
159 | + * ) | ||
160 | + */ | ||
161 | + public function delete() | ||
162 | + { | ||
163 | + $id = $this->request->param('id', 0, 'intval'); | ||
164 | + LinkModel::destroy($id); | ||
165 | + $this->success("删除成功!", url("link/index")); | ||
166 | + } | ||
167 | + | ||
168 | + /** | ||
169 | + * 友情链接排序 | ||
170 | + * @adminMenu( | ||
171 | + * 'name' => '友情链接排序', | ||
172 | + * 'parent' => 'index', | ||
173 | + * 'display'=> false, | ||
174 | + * 'hasView'=> false, | ||
175 | + * 'order' => 10000, | ||
176 | + * 'icon' => '', | ||
177 | + * 'remark' => '友情链接排序', | ||
178 | + * 'param' => '' | ||
179 | + * ) | ||
180 | + */ | ||
181 | + public function listOrder() | ||
182 | + { | ||
183 | + $linkModel = new LinkModel(); | ||
184 | + parent::listOrders($linkModel); | ||
185 | + $this->success("排序更新成功!"); | ||
186 | + } | ||
187 | + | ||
188 | + /** | ||
189 | + * 友情链接显示隐藏 | ||
190 | + * @adminMenu( | ||
191 | + * 'name' => '友情链接显示隐藏', | ||
192 | + * 'parent' => 'index', | ||
193 | + * 'display'=> false, | ||
194 | + * 'hasView'=> false, | ||
195 | + * 'order' => 10000, | ||
196 | + * 'icon' => '', | ||
197 | + * 'remark' => '友情链接显示隐藏', | ||
198 | + * 'param' => '' | ||
199 | + * ) | ||
200 | + */ | ||
201 | + public function toggle() | ||
202 | + { | ||
203 | + $data = $this->request->param(); | ||
204 | + $linkModel = new LinkModel(); | ||
205 | + | ||
206 | + if (isset($data['ids']) && !empty($data["display"])) { | ||
207 | + $ids = $this->request->param('ids/a'); | ||
208 | + $linkModel->where('id', 'in', $ids)->update(['status' => 1]); | ||
209 | + $this->success("更新成功!"); | ||
210 | + } | ||
211 | + | ||
212 | + if (isset($data['ids']) && !empty($data["hide"])) { | ||
213 | + $ids = $this->request->param('ids/a'); | ||
214 | + $linkModel->where('id', 'in', $ids)->update(['status' => 0]); | ||
215 | + $this->success("更新成功!"); | ||
216 | + } | ||
217 | + | ||
218 | + | ||
219 | + } | ||
220 | + | ||
221 | +} |
app/admin/controller/MailerController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use think\Validate; | ||
15 | + | ||
16 | +class MailerController extends AdminBaseController | ||
17 | +{ | ||
18 | + | ||
19 | + /** | ||
20 | + * 邮箱配置 | ||
21 | + * @adminMenu( | ||
22 | + * 'name' => '邮箱配置', | ||
23 | + * 'parent' => 'admin/Setting/default', | ||
24 | + * 'display'=> true, | ||
25 | + * 'hasView'=> true, | ||
26 | + * 'order' => 10, | ||
27 | + * 'icon' => '', | ||
28 | + * 'remark' => '邮箱配置', | ||
29 | + * 'param' => '' | ||
30 | + * ) | ||
31 | + */ | ||
32 | + public function index() | ||
33 | + { | ||
34 | + $emailSetting = cmf_get_option('smtp_setting'); | ||
35 | + $this->assign($emailSetting); | ||
36 | + return $this->fetch(); | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * 邮箱配置 | ||
41 | + * @adminMenu( | ||
42 | + * 'name' => '邮箱配置提交保存', | ||
43 | + * 'parent' => 'index', | ||
44 | + * 'display'=> false, | ||
45 | + * 'hasView'=> false, | ||
46 | + * 'order' => 10000, | ||
47 | + * 'icon' => '', | ||
48 | + * 'remark' => '邮箱配置提交保存', | ||
49 | + * 'param' => '' | ||
50 | + * ) | ||
51 | + */ | ||
52 | + public function indexPost() | ||
53 | + { | ||
54 | + $post = array_map('trim', $this->request->param()); | ||
55 | + | ||
56 | + if (in_array('', $post) && !empty($post['smtpsecure'])) { | ||
57 | + $this->error("不能留空!"); | ||
58 | + } | ||
59 | + | ||
60 | + cmf_set_option('smtp_setting', $post); | ||
61 | + | ||
62 | + $this->success("保存成功!"); | ||
63 | + } | ||
64 | + | ||
65 | + /** | ||
66 | + * 邮件模板 | ||
67 | + * @adminMenu( | ||
68 | + * 'name' => '邮件模板', | ||
69 | + * 'parent' => 'index', | ||
70 | + * 'display'=> false, | ||
71 | + * 'hasView'=> true, | ||
72 | + * 'order' => 10000, | ||
73 | + * 'icon' => '', | ||
74 | + * 'remark' => '邮件模板', | ||
75 | + * 'param' => '' | ||
76 | + * ) | ||
77 | + */ | ||
78 | + public function template() | ||
79 | + { | ||
80 | + $allowedTemplateKeys = ['verification_code']; | ||
81 | + $templateKey = $this->request->param('template_key'); | ||
82 | + | ||
83 | + if (empty($templateKey) || !in_array($templateKey, $allowedTemplateKeys)) { | ||
84 | + $this->error('非法请求!'); | ||
85 | + } | ||
86 | + | ||
87 | + $template = cmf_get_option('email_template_' . $templateKey); | ||
88 | + $this->assign($template); | ||
89 | + return $this->fetch('template_verification_code'); | ||
90 | + } | ||
91 | + | ||
92 | + /** | ||
93 | + * 邮件模板提交 | ||
94 | + * @adminMenu( | ||
95 | + * 'name' => '邮件模板提交', | ||
96 | + * 'parent' => 'index', | ||
97 | + * 'display'=> false, | ||
98 | + * 'hasView'=> false, | ||
99 | + * 'order' => 10000, | ||
100 | + * 'icon' => '', | ||
101 | + * 'remark' => '邮件模板提交', | ||
102 | + * 'param' => '' | ||
103 | + * ) | ||
104 | + */ | ||
105 | + public function templatePost() | ||
106 | + { | ||
107 | + $allowedTemplateKeys = ['verification_code']; | ||
108 | + $templateKey = $this->request->param('template_key'); | ||
109 | + | ||
110 | + if (empty($templateKey) || !in_array($templateKey, $allowedTemplateKeys)) { | ||
111 | + $this->error('非法请求!'); | ||
112 | + } | ||
113 | + | ||
114 | + $data = $this->request->param(); | ||
115 | + | ||
116 | + unset($data['template_key']); | ||
117 | + | ||
118 | + cmf_set_option('email_template_' . $templateKey, $data); | ||
119 | + | ||
120 | + $this->success("保存成功!"); | ||
121 | + } | ||
122 | + | ||
123 | + /** | ||
124 | + * 邮件发送测试 | ||
125 | + * @adminMenu( | ||
126 | + * 'name' => '邮件发送测试', | ||
127 | + * 'parent' => 'index', | ||
128 | + * 'display'=> false, | ||
129 | + * 'hasView'=> true, | ||
130 | + * 'order' => 10000, | ||
131 | + * 'icon' => '', | ||
132 | + * 'remark' => '邮件发送测试', | ||
133 | + * 'param' => '' | ||
134 | + * ) | ||
135 | + */ | ||
136 | + public function test() | ||
137 | + { | ||
138 | + if ($this->request->isPost()) { | ||
139 | + | ||
140 | + $validate = new Validate([ | ||
141 | + 'to' => 'require|email', | ||
142 | + 'subject' => 'require', | ||
143 | + 'content' => 'require', | ||
144 | + ]); | ||
145 | + $validate->message([ | ||
146 | + 'to.require' => '收件箱不能为空!', | ||
147 | + 'to.email' => '收件箱格式不正确!', | ||
148 | + 'subject.require' => '标题不能为空!', | ||
149 | + 'content.require' => '内容不能为空!', | ||
150 | + ]); | ||
151 | + | ||
152 | + $data = $this->request->param(); | ||
153 | + if (!$validate->check($data)) { | ||
154 | + $this->error($validate->getError()); | ||
155 | + } | ||
156 | + | ||
157 | + $result = cmf_send_email($data['to'], $data['subject'], $data['content']); | ||
158 | + if ($result && empty($result['error'])) { | ||
159 | + $this->success('发送成功!'); | ||
160 | + } else { | ||
161 | + $this->error('发送失败:' . $result['message']); | ||
162 | + } | ||
163 | + | ||
164 | + } else { | ||
165 | + return $this->fetch(); | ||
166 | + } | ||
167 | + | ||
168 | + } | ||
169 | + | ||
170 | + | ||
171 | +} | ||
172 | + |
app/admin/controller/MainController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use think\Db; | ||
15 | +use app\admin\model\Menu; | ||
16 | + | ||
17 | +class MainController extends AdminBaseController | ||
18 | +{ | ||
19 | + | ||
20 | + /** | ||
21 | + * 后台欢迎页 | ||
22 | + */ | ||
23 | + public function index() | ||
24 | + { | ||
25 | + $dashboardWidgets = []; | ||
26 | + $widgets = cmf_get_option('admin_dashboard_widgets'); | ||
27 | + | ||
28 | + $defaultDashboardWidgets = [ | ||
29 | + '_SystemCmfHub' => ['name' => 'CmfHub', 'is_system' => 1], | ||
30 | + '_SystemCmfDocuments' => ['name' => 'CmfDocuments', 'is_system' => 1], | ||
31 | + '_SystemMainContributors' => ['name' => 'MainContributors', 'is_system' => 1], | ||
32 | + '_SystemContributors' => ['name' => 'Contributors', 'is_system' => 1], | ||
33 | + '_SystemCustom1' => ['name' => 'Custom1', 'is_system' => 1], | ||
34 | + '_SystemCustom2' => ['name' => 'Custom2', 'is_system' => 1], | ||
35 | + '_SystemCustom3' => ['name' => 'Custom3', 'is_system' => 1], | ||
36 | + '_SystemCustom4' => ['name' => 'Custom4', 'is_system' => 1], | ||
37 | + '_SystemCustom5' => ['name' => 'Custom5', 'is_system' => 1], | ||
38 | + ]; | ||
39 | + | ||
40 | + if (empty($widgets)) { | ||
41 | + $dashboardWidgets = $defaultDashboardWidgets; | ||
42 | + } else { | ||
43 | + foreach ($widgets as $widget) { | ||
44 | + if ($widget['is_system']) { | ||
45 | + $dashboardWidgets['_System' . $widget['name']] = ['name' => $widget['name'], 'is_system' => 1]; | ||
46 | + } else { | ||
47 | + $dashboardWidgets[$widget['name']] = ['name' => $widget['name'], 'is_system' => 0]; | ||
48 | + } | ||
49 | + } | ||
50 | + | ||
51 | + foreach ($defaultDashboardWidgets as $widgetName => $widget) { | ||
52 | + $dashboardWidgets[$widgetName] = $widget; | ||
53 | + } | ||
54 | + | ||
55 | + | ||
56 | + } | ||
57 | + | ||
58 | + $dashboardWidgetPlugins = []; | ||
59 | + | ||
60 | + $hookResults = hook('admin_dashboard'); | ||
61 | + | ||
62 | + if (!empty($hookResults)) { | ||
63 | + foreach ($hookResults as $hookResult) { | ||
64 | + if (isset($hookResult['width']) && isset($hookResult['view']) && isset($hookResult['plugin'])) { //验证插件返回合法性 | ||
65 | + $dashboardWidgetPlugins[$hookResult['plugin']] = $hookResult; | ||
66 | + if (!isset($dashboardWidgets[$hookResult['plugin']])) { | ||
67 | + $dashboardWidgets[$hookResult['plugin']] = ['name' => $hookResult['plugin'], 'is_system' => 0]; | ||
68 | + } | ||
69 | + } | ||
70 | + } | ||
71 | + } | ||
72 | + | ||
73 | + $smtpSetting = cmf_get_option('smtp_setting'); | ||
74 | + | ||
75 | + $this->assign('dashboard_widgets', $dashboardWidgets); | ||
76 | + $this->assign('dashboard_widget_plugins', $dashboardWidgetPlugins); | ||
77 | + $this->assign('has_smtp_setting', empty($smtpSetting) ? false : true); | ||
78 | + | ||
79 | + return $this->fetch(); | ||
80 | + } | ||
81 | + | ||
82 | + public function dashboardWidget() | ||
83 | + { | ||
84 | + $dashboardWidgets = []; | ||
85 | + $widgets = $this->request->param('widgets/a'); | ||
86 | + if (!empty($widgets)) { | ||
87 | + foreach ($widgets as $widget) { | ||
88 | + if ($widget['is_system']) { | ||
89 | + array_push($dashboardWidgets, ['name' => $widget['name'], 'is_system' => 1]); | ||
90 | + } else { | ||
91 | + array_push($dashboardWidgets, ['name' => $widget['name'], 'is_system' => 0]); | ||
92 | + } | ||
93 | + } | ||
94 | + } | ||
95 | + | ||
96 | + cmf_set_option('admin_dashboard_widgets', $dashboardWidgets, true); | ||
97 | + | ||
98 | + $this->success('更新成功!'); | ||
99 | + | ||
100 | + } | ||
101 | + | ||
102 | +} |
app/admin/controller/MenuController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use app\admin\model\AdminMenuModel; | ||
14 | +use cmf\controller\AdminBaseController; | ||
15 | +use think\Db; | ||
16 | +use think\facade\Cache; | ||
17 | +use tree\Tree; | ||
18 | +use mindplay\annotations\Annotations; | ||
19 | + | ||
20 | +class MenuController extends AdminBaseController | ||
21 | +{ | ||
22 | + /** | ||
23 | + * 后台菜单管理 | ||
24 | + * @adminMenu( | ||
25 | + * 'name' => '后台菜单', | ||
26 | + * 'parent' => 'admin/Setting/default', | ||
27 | + * 'display'=> false, | ||
28 | + * 'hasView'=> true, | ||
29 | + * 'order' => 10000, | ||
30 | + * 'icon' => '', | ||
31 | + * 'remark' => '后台菜单管理', | ||
32 | + * 'param' => '' | ||
33 | + * ) | ||
34 | + * @return mixed | ||
35 | + * @throws \think\db\exception\DataNotFoundException | ||
36 | + * @throws \think\db\exception\ModelNotFoundException | ||
37 | + * @throws \think\exception\DbException | ||
38 | + */ | ||
39 | + public function index() | ||
40 | + { | ||
41 | + $content = hook_one('admin_menu_index_view'); | ||
42 | + | ||
43 | + if (!empty($content)) { | ||
44 | + return $content; | ||
45 | + } | ||
46 | + | ||
47 | + session('admin_menu_index', 'Menu/index'); | ||
48 | + $result = Db::name('AdminMenu')->order(["list_order" => "ASC"])->select()->toArray(); | ||
49 | + $tree = new Tree(); | ||
50 | + $tree->icon = [' │ ', ' ├─', ' └─ ']; | ||
51 | + $tree->nbsp = ' '; | ||
52 | + | ||
53 | + $newMenus = []; | ||
54 | + foreach ($result as $m) { | ||
55 | + $newMenus[$m['id']] = $m; | ||
56 | + } | ||
57 | + foreach ($result as $key => $value) { | ||
58 | + | ||
59 | + $result[$key]['parent_id_node'] = ($value['parent_id']) ? ' class="child-of-node-' . $value['parent_id'] . '"' : ''; | ||
60 | + $result[$key]['style'] = empty($value['parent_id']) ? '' : 'display:none;'; | ||
61 | + $result[$key]['str_manage'] = '<a class="btn btn-xs btn-primary" href="' . url("Menu/add", ["parent_id" => $value['id'], "menu_id" => $this->request->param("menu_id")]) . '">' . lang('ADD_SUB_MENU') . '</a> | ||
62 | + <a class="btn btn-xs btn-primary" href="' . url("Menu/edit", ["id" => $value['id'], "menu_id" => $this->request->param("menu_id")]) . '">' . lang('EDIT') . '</a> | ||
63 | + <a class="btn btn-xs btn-danger js-ajax-delete" href="' . url("Menu/delete", ["id" => $value['id'], "menu_id" => $this->request->param("menu_id")]) . '">' . lang('DELETE') . '</a> '; | ||
64 | + $result[$key]['status'] = $value['status'] ? '<span class="label label-success">' . lang('DISPLAY') . '</span>' : '<span class="label label-warning">' . lang('HIDDEN') . '</span>'; | ||
65 | + if (APP_DEBUG) { | ||
66 | + $result[$key]['app'] = $value['app'] . "/" . $value['controller'] . "/" . $value['action']; | ||
67 | + } | ||
68 | + } | ||
69 | + | ||
70 | + $tree->init($result); | ||
71 | + $str = "<tr id='node-\$id' \$parent_id_node style='\$style'> | ||
72 | + <td style='padding-left:20px;'><input name='list_orders[\$id]' type='text' size='3' value='\$list_order' class='input input-order'></td> | ||
73 | + <td>\$id</td> | ||
74 | + <td>\$spacer\$name</td> | ||
75 | + <td>\$app</td> | ||
76 | + <td>\$status</td> | ||
77 | + <td>\$str_manage</td> | ||
78 | + </tr>"; | ||
79 | + $category = $tree->getTree(0, $str); | ||
80 | + $this->assign("category", $category); | ||
81 | + return $this->fetch(); | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * 后台所有菜单列表 | ||
86 | + * @adminMenu( | ||
87 | + * 'name' => '所有菜单', | ||
88 | + * 'parent' => 'index', | ||
89 | + * 'display'=> false, | ||
90 | + * 'hasView'=> true, | ||
91 | + * 'order' => 10000, | ||
92 | + * 'icon' => '', | ||
93 | + * 'remark' => '后台所有菜单列表', | ||
94 | + * 'param' => '' | ||
95 | + * ) | ||
96 | + * @return mixed | ||
97 | + * @throws \think\db\exception\DataNotFoundException | ||
98 | + * @throws \think\db\exception\ModelNotFoundException | ||
99 | + * @throws \think\exception\DbException | ||
100 | + */ | ||
101 | + public function lists() | ||
102 | + { | ||
103 | + session('admin_menu_index', 'Menu/lists'); | ||
104 | + $result = Db::name('AdminMenu')->order(["app" => "ASC", "controller" => "ASC", "action" => "ASC"])->select(); | ||
105 | + $this->assign("menus", $result); | ||
106 | + return $this->fetch(); | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * 后台菜单添加 | ||
111 | + * @adminMenu( | ||
112 | + * 'name' => '后台菜单添加', | ||
113 | + * 'parent' => 'index', | ||
114 | + * 'display'=> false, | ||
115 | + * 'hasView'=> true, | ||
116 | + * 'order' => 10000, | ||
117 | + * 'icon' => '', | ||
118 | + * 'remark' => '后台菜单添加', | ||
119 | + * 'param' => '' | ||
120 | + * ) | ||
121 | + * @return mixed | ||
122 | + * @throws \think\db\exception\DataNotFoundException | ||
123 | + * @throws \think\db\exception\ModelNotFoundException | ||
124 | + * @throws \think\exception\DbException | ||
125 | + */ | ||
126 | + public function add() | ||
127 | + { | ||
128 | + $tree = new Tree(); | ||
129 | + $parentId = $this->request->param("parent_id", 0, 'intval'); | ||
130 | + $result = Db::name('AdminMenu')->order(["list_order" => "ASC"])->select(); | ||
131 | + $array = []; | ||
132 | + foreach ($result as $r) { | ||
133 | + $r['selected'] = $r['id'] == $parentId ? 'selected' : ''; | ||
134 | + $array[] = $r; | ||
135 | + } | ||
136 | + $str = "<option value='\$id' \$selected>\$spacer \$name</option>"; | ||
137 | + $tree->init($array); | ||
138 | + $selectCategory = $tree->getTree(0, $str); | ||
139 | + $this->assign("select_category", $selectCategory); | ||
140 | + return $this->fetch(); | ||
141 | + } | ||
142 | + | ||
143 | + /** | ||
144 | + * 后台菜单添加提交保存 | ||
145 | + * @adminMenu( | ||
146 | + * 'name' => '后台菜单添加提交保存', | ||
147 | + * 'parent' => 'index', | ||
148 | + * 'display'=> false, | ||
149 | + * 'hasView'=> false, | ||
150 | + * 'order' => 10000, | ||
151 | + * 'icon' => '', | ||
152 | + * 'remark' => '后台菜单添加提交保存', | ||
153 | + * 'param' => '' | ||
154 | + * ) | ||
155 | + */ | ||
156 | + public function addPost() | ||
157 | + { | ||
158 | + if ($this->request->isPost()) { | ||
159 | + $result = $this->validate($this->request->param(), 'AdminMenu'); | ||
160 | + if ($result !== true) { | ||
161 | + $this->error($result); | ||
162 | + } else { | ||
163 | + $data = $this->request->param(); | ||
164 | + Db::name('AdminMenu')->strict(false)->field(true)->insert($data); | ||
165 | + | ||
166 | + $app = $this->request->param("app"); | ||
167 | + $controller = $this->request->param("controller"); | ||
168 | + $action = $this->request->param("action"); | ||
169 | + $param = $this->request->param("param"); | ||
170 | + $authRuleName = "$app/$controller/$action"; | ||
171 | + $menuName = $this->request->param("name"); | ||
172 | + | ||
173 | + $findAuthRuleCount = Db::name('auth_rule')->where([ | ||
174 | + 'app' => $app, | ||
175 | + 'name' => $authRuleName, | ||
176 | + 'type' => 'admin_url' | ||
177 | + ])->count(); | ||
178 | + if (empty($findAuthRuleCount)) { | ||
179 | + Db::name('AuthRule')->insert([ | ||
180 | + "name" => $authRuleName, | ||
181 | + "app" => $app, | ||
182 | + "type" => "admin_url", //type 1-admin rule;2-user rule | ||
183 | + "title" => $menuName, | ||
184 | + 'param' => $param, | ||
185 | + ]); | ||
186 | + } | ||
187 | + $sessionAdminMenuIndex = session('admin_menu_index'); | ||
188 | + $to = empty($sessionAdminMenuIndex) ? "Menu/index" : $sessionAdminMenuIndex; | ||
189 | + $this->_exportAppMenuDefaultLang(); | ||
190 | + Cache::clear('admin_menus');// 删除后台菜单缓存 | ||
191 | + $this->success("添加成功!", url($to)); | ||
192 | + } | ||
193 | + } | ||
194 | + } | ||
195 | + | ||
196 | + /** | ||
197 | + * 后台菜单编辑 | ||
198 | + * @adminMenu( | ||
199 | + * 'name' => '后台菜单编辑', | ||
200 | + * 'parent' => 'index', | ||
201 | + * 'display'=> false, | ||
202 | + * 'hasView'=> true, | ||
203 | + * 'order' => 10000, | ||
204 | + * 'icon' => '', | ||
205 | + * 'remark' => '后台菜单编辑', | ||
206 | + * 'param' => '' | ||
207 | + * ) | ||
208 | + * @return mixed | ||
209 | + * @throws \think\db\exception\DataNotFoundException | ||
210 | + * @throws \think\db\exception\ModelNotFoundException | ||
211 | + * @throws \think\exception\DbException | ||
212 | + */ | ||
213 | + public function edit() | ||
214 | + { | ||
215 | + $tree = new Tree(); | ||
216 | + $id = $this->request->param("id", 0, 'intval'); | ||
217 | + $rs = Db::name('AdminMenu')->where("id", $id)->find(); | ||
218 | + $result = Db::name('AdminMenu')->order(["list_order" => "ASC"])->select(); | ||
219 | + $array = []; | ||
220 | + foreach ($result as $r) { | ||
221 | + $r['selected'] = $r['id'] == $rs['parent_id'] ? 'selected' : ''; | ||
222 | + $array[] = $r; | ||
223 | + } | ||
224 | + $str = "<option value='\$id' \$selected>\$spacer \$name</option>"; | ||
225 | + $tree->init($array); | ||
226 | + $selectCategory = $tree->getTree(0, $str); | ||
227 | + $this->assign("data", $rs); | ||
228 | + $this->assign("select_category", $selectCategory); | ||
229 | + return $this->fetch(); | ||
230 | + } | ||
231 | + | ||
232 | + /** | ||
233 | + * 后台菜单编辑提交保存 | ||
234 | + * @adminMenu( | ||
235 | + * 'name' => '后台菜单编辑提交保存', | ||
236 | + * 'parent' => 'index', | ||
237 | + * 'display'=> false, | ||
238 | + * 'hasView'=> false, | ||
239 | + * 'order' => 10000, | ||
240 | + * 'icon' => '', | ||
241 | + * 'remark' => '后台菜单编辑提交保存', | ||
242 | + * 'param' => '' | ||
243 | + * ) | ||
244 | + * @throws \think\Exception | ||
245 | + * @throws \think\db\exception\DataNotFoundException | ||
246 | + * @throws \think\db\exception\ModelNotFoundException | ||
247 | + * @throws \think\exception\DbException | ||
248 | + * @throws \think\exception\PDOException | ||
249 | + */ | ||
250 | + public function editPost() | ||
251 | + { | ||
252 | + if ($this->request->isPost()) { | ||
253 | + $id = $this->request->param('id', 0, 'intval'); | ||
254 | + $oldMenu = Db::name('AdminMenu')->where('id', $id)->find(); | ||
255 | + | ||
256 | + $result = $this->validate($this->request->param(), 'AdminMenu.edit'); | ||
257 | + | ||
258 | + if ($result !== true) { | ||
259 | + $this->error($result); | ||
260 | + } else { | ||
261 | + Db::name('AdminMenu')->strict(false)->field(true)->update($this->request->param()); | ||
262 | + $app = $this->request->param("app"); | ||
263 | + $controller = $this->request->param("controller"); | ||
264 | + $action = $this->request->param("action"); | ||
265 | + $param = $this->request->param("param"); | ||
266 | + $authRuleName = "$app/$controller/$action"; | ||
267 | + $menuName = $this->request->param("name"); | ||
268 | + | ||
269 | + $findAuthRuleCount = Db::name('auth_rule')->where([ | ||
270 | + 'app' => $app, | ||
271 | + 'name' => $authRuleName, | ||
272 | + 'type' => 'admin_url' | ||
273 | + ])->count(); | ||
274 | + if (empty($findAuthRuleCount)) { | ||
275 | + $oldApp = $oldMenu['app']; | ||
276 | + $oldController = $oldMenu['controller']; | ||
277 | + $oldAction = $oldMenu['action']; | ||
278 | + $oldName = "$oldApp/$oldController/$oldAction"; | ||
279 | + $findOldRuleId = Db::name('AuthRule')->where("name", $oldName)->value('id'); | ||
280 | + if (empty($findOldRuleId)) { | ||
281 | + Db::name('AuthRule')->insert([ | ||
282 | + "name" => $authRuleName, | ||
283 | + "app" => $app, | ||
284 | + "type" => "admin_url", | ||
285 | + "title" => $menuName, | ||
286 | + "param" => $param | ||
287 | + ]);//type 1-admin rule;2-user rule | ||
288 | + } else { | ||
289 | + Db::name('AuthRule')->where('id', $findOldRuleId)->update([ | ||
290 | + "name" => $authRuleName, | ||
291 | + "app" => $app, | ||
292 | + "type" => "admin_url", | ||
293 | + "title" => $menuName, | ||
294 | + "param" => $param]);//type 1-admin rule;2-user rule | ||
295 | + } | ||
296 | + } else { | ||
297 | + Db::name('AuthRule')->where([ | ||
298 | + 'app' => $app, | ||
299 | + 'name' => $authRuleName, | ||
300 | + 'type' => 'admin_url' | ||
301 | + ])->update(["title" => $menuName, 'param' => $param]);//type 1-admin rule;2-user rule | ||
302 | + } | ||
303 | + $this->_exportAppMenuDefaultLang(); | ||
304 | + Cache::clear('admin_menus');// 删除后台菜单缓存 | ||
305 | + $this->success("保存成功!"); | ||
306 | + } | ||
307 | + } | ||
308 | + } | ||
309 | + | ||
310 | + /** | ||
311 | + * 后台菜单删除 | ||
312 | + * @adminMenu( | ||
313 | + * 'name' => '后台菜单删除', | ||
314 | + * 'parent' => 'index', | ||
315 | + * 'display'=> false, | ||
316 | + * 'hasView'=> false, | ||
317 | + * 'order' => 10000, | ||
318 | + * 'icon' => '', | ||
319 | + * 'remark' => '后台菜单删除', | ||
320 | + * 'param' => '' | ||
321 | + * ) | ||
322 | + * @throws \think\Exception | ||
323 | + * @throws \think\exception\PDOException | ||
324 | + */ | ||
325 | + public function delete() | ||
326 | + { | ||
327 | + $id = $this->request->param("id", 0, 'intval'); | ||
328 | + $count = Db::name('AdminMenu')->where("parent_id", $id)->count(); | ||
329 | + if ($count > 0) { | ||
330 | + $this->error("该菜单下还有子菜单,无法删除!"); | ||
331 | + } | ||
332 | + if (Db::name('AdminMenu')->delete($id) !== false) { | ||
333 | + $this->success("删除菜单成功!"); | ||
334 | + } else { | ||
335 | + $this->error("删除失败!"); | ||
336 | + } | ||
337 | + } | ||
338 | + | ||
339 | + /** | ||
340 | + * 后台菜单排序 | ||
341 | + * @adminMenu( | ||
342 | + * 'name' => '后台菜单排序', | ||
343 | + * 'parent' => 'index', | ||
344 | + * 'display'=> false, | ||
345 | + * 'hasView'=> false, | ||
346 | + * 'order' => 10000, | ||
347 | + * 'icon' => '', | ||
348 | + * 'remark' => '后台菜单排序', | ||
349 | + * 'param' => '' | ||
350 | + * ) | ||
351 | + */ | ||
352 | + public function listOrder() | ||
353 | + { | ||
354 | + $adminMenuModel = new AdminMenuModel(); | ||
355 | + parent::listOrders($adminMenuModel); | ||
356 | + $this->success("排序更新成功!"); | ||
357 | + } | ||
358 | + | ||
359 | + /** | ||
360 | + * 导入新后台菜单 | ||
361 | + * @adminMenu( | ||
362 | + * 'name' => '导入新后台菜单', | ||
363 | + * 'parent' => 'index', | ||
364 | + * 'display'=> false, | ||
365 | + * 'hasView'=> true, | ||
366 | + * 'order' => 10000, | ||
367 | + * 'icon' => '', | ||
368 | + * 'remark' => '导入新后台菜单', | ||
369 | + * 'param' => '' | ||
370 | + * ) | ||
371 | + * @return mixed | ||
372 | + * @throws \ReflectionException | ||
373 | + * @throws \think\Exception | ||
374 | + * @throws \think\db\exception\DataNotFoundException | ||
375 | + * @throws \think\db\exception\ModelNotFoundException | ||
376 | + * @throws \think\exception\DbException | ||
377 | + * @throws \think\exception\PDOException | ||
378 | + */ | ||
379 | + public function getActions() | ||
380 | + { | ||
381 | + Annotations::$config['cache'] = false; | ||
382 | + $annotationManager = Annotations::getManager(); | ||
383 | + $annotationManager->registry['adminMenu'] = 'app\admin\annotation\AdminMenuAnnotation'; | ||
384 | + $annotationManager->registry['adminMenuRoot'] = 'app\admin\annotation\AdminMenuRootAnnotation'; | ||
385 | + $newMenus = []; | ||
386 | + | ||
387 | + $apps = cmf_scan_dir(APP_PATH . '*', GLOB_ONLYDIR); | ||
388 | + | ||
389 | + $app = $this->request->param('app', ''); | ||
390 | + if (empty($app)) { | ||
391 | + $app = $apps[0]; | ||
392 | + } | ||
393 | + | ||
394 | + if (!in_array($app, $apps)) { | ||
395 | + $this->error('应用' . $app . '不存在!'); | ||
396 | + } | ||
397 | + | ||
398 | + if ($app == 'admin') { | ||
399 | + $filePatten = APP_PATH . $app . '/controller/*Controller.php'; | ||
400 | + } else { | ||
401 | + $filePatten = APP_PATH . $app . '/controller/Admin*Controller.php'; | ||
402 | + } | ||
403 | + | ||
404 | + $controllers = cmf_scan_dir($filePatten); | ||
405 | + | ||
406 | + if (!empty($controllers)) { | ||
407 | + foreach ($controllers as $controller) { | ||
408 | + $controller = preg_replace('/\.php$/', '', $controller); | ||
409 | + $controllerName = preg_replace('/\Controller$/', '', $controller); | ||
410 | + $controllerClass = "app\\$app\\controller\\$controller"; | ||
411 | + | ||
412 | + $menuAnnotations = Annotations::ofClass($controllerClass, '@adminMenuRoot'); | ||
413 | + | ||
414 | + if (!empty($menuAnnotations)) { | ||
415 | + foreach ($menuAnnotations as $menuAnnotation) { | ||
416 | + | ||
417 | + $name = $menuAnnotation->name; | ||
418 | + $icon = $menuAnnotation->icon; | ||
419 | + $type = 0;//1:有界面可访问菜单,2:无界面可访问菜单,0:只作为菜单 | ||
420 | + $action = $menuAnnotation->action; | ||
421 | + $status = empty($menuAnnotation->display) ? 0 : 1; | ||
422 | + $listOrder = floatval($menuAnnotation->order); | ||
423 | + $param = $menuAnnotation->param; | ||
424 | + $remark = $menuAnnotation->remark; | ||
425 | + | ||
426 | + if (empty($menuAnnotation->parent)) { | ||
427 | + $parentId = 0; | ||
428 | + } else { | ||
429 | + | ||
430 | + $parent = explode('/', $menuAnnotation->parent); | ||
431 | + $countParent = count($parent); | ||
432 | + if ($countParent > 3) { | ||
433 | + throw new \Exception($controllerClass . ':' . $action . ' @adminMenuRoot parent格式不正确!'); | ||
434 | + } | ||
435 | + | ||
436 | + $parentApp = $app; | ||
437 | + $parentController = $controllerName; | ||
438 | + $parentAction = ''; | ||
439 | + | ||
440 | + switch ($countParent) { | ||
441 | + case 1: | ||
442 | + $parentAction = $parent[0]; | ||
443 | + break; | ||
444 | + case 2: | ||
445 | + $parentController = $parent[0]; | ||
446 | + $parentAction = $parent[1]; | ||
447 | + break; | ||
448 | + case 3: | ||
449 | + $parentApp = $parent[0]; | ||
450 | + $parentController = $parent[1]; | ||
451 | + $parentAction = $parent[2]; | ||
452 | + break; | ||
453 | + } | ||
454 | + | ||
455 | + $findParentAdminMenu = Db::name('admin_menu')->where([ | ||
456 | + 'app' => $parentApp, | ||
457 | + 'controller' => $parentController, | ||
458 | + 'action' => $parentAction | ||
459 | + ])->find(); | ||
460 | + | ||
461 | + if (empty($findParentAdminMenu)) { | ||
462 | + $parentId = Db::name('admin_menu')->insertGetId([ | ||
463 | + 'app' => $parentApp, | ||
464 | + 'controller' => $parentController, | ||
465 | + 'action' => $parentAction, | ||
466 | + 'name' => '--new--' | ||
467 | + ]); | ||
468 | + } else { | ||
469 | + $parentId = $findParentAdminMenu['id']; | ||
470 | + } | ||
471 | + } | ||
472 | + | ||
473 | + $findAdminMenu = Db::name('admin_menu')->where([ | ||
474 | + 'app' => $app, | ||
475 | + 'controller' => $controllerName, | ||
476 | + 'action' => $action | ||
477 | + ])->find(); | ||
478 | + | ||
479 | + if (empty($findAdminMenu)) { | ||
480 | + | ||
481 | + Db::name('admin_menu')->insert([ | ||
482 | + 'parent_id' => $parentId, | ||
483 | + 'type' => $type, | ||
484 | + 'status' => $status, | ||
485 | + 'list_order' => $listOrder, | ||
486 | + 'app' => $app, | ||
487 | + 'controller' => $controllerName, | ||
488 | + 'action' => $action, | ||
489 | + 'param' => $param, | ||
490 | + 'name' => $name, | ||
491 | + 'icon' => $icon, | ||
492 | + 'remark' => $remark | ||
493 | + ]); | ||
494 | + | ||
495 | + $menuName = $name; | ||
496 | + | ||
497 | + array_push($newMenus, "$app/$controllerName/$action 已导入"); | ||
498 | + | ||
499 | + } else { | ||
500 | + | ||
501 | + if ($findAdminMenu['name'] == '--new--') { | ||
502 | + Db::name('admin_menu')->where([ | ||
503 | + 'app' => $app, | ||
504 | + 'controller' => $controllerName, | ||
505 | + 'action' => $action | ||
506 | + ])->update([ | ||
507 | + 'parent_id' => $parentId, | ||
508 | + 'type' => $type, | ||
509 | + 'status' => $status, | ||
510 | + 'list_order' => $listOrder, | ||
511 | + 'param' => $param, | ||
512 | + 'name' => $name, | ||
513 | + 'icon' => $icon, | ||
514 | + 'remark' => $remark | ||
515 | + ]); | ||
516 | + $menuName = $name; | ||
517 | + } else { | ||
518 | + // 只关注菜单层级关系,是否有视图 | ||
519 | + Db::name('admin_menu')->where([ | ||
520 | + 'app' => $app, | ||
521 | + 'controller' => $controllerName, | ||
522 | + 'action' => $action | ||
523 | + ])->update([ | ||
524 | + //'parent_id' => $parentId, | ||
525 | + 'type' => $type, | ||
526 | + ]); | ||
527 | + $menuName = $findAdminMenu['name']; | ||
528 | + } | ||
529 | + | ||
530 | + array_push($newMenus, "$app/$controllerName/$action 层级关系已更新"); | ||
531 | + } | ||
532 | + | ||
533 | + $authRuleName = "{$app}/{$controllerName}/{$action}"; | ||
534 | + $findAuthRuleCount = Db::name('auth_rule')->where([ | ||
535 | + 'app' => $app, | ||
536 | + 'name' => $authRuleName, | ||
537 | + 'type' => 'admin_url' | ||
538 | + ])->count(); | ||
539 | + | ||
540 | + if ($findAuthRuleCount == 0) { | ||
541 | + Db::name('auth_rule')->insert([ | ||
542 | + 'app' => $app, | ||
543 | + 'name' => $authRuleName, | ||
544 | + 'type' => 'admin_url', | ||
545 | + 'param' => $param, | ||
546 | + 'title' => $menuName | ||
547 | + ]); | ||
548 | + } else { | ||
549 | + Db::name('auth_rule')->where([ | ||
550 | + 'app' => $app, | ||
551 | + 'name' => $authRuleName, | ||
552 | + 'type' => 'admin_url', | ||
553 | + ])->update([ | ||
554 | + 'param' => $param, | ||
555 | + 'title' => $menuName | ||
556 | + ]); | ||
557 | + } | ||
558 | + | ||
559 | + } | ||
560 | + } | ||
561 | + | ||
562 | + $reflect = new \ReflectionClass($controllerClass); | ||
563 | + $methods = $reflect->getMethods(\ReflectionMethod::IS_PUBLIC); | ||
564 | + | ||
565 | + if (!empty($methods)) { | ||
566 | + foreach ($methods as $method) { | ||
567 | + | ||
568 | + if ($method->class == $controllerClass && strpos($method->name, '_') !== 0) { | ||
569 | + $menuAnnotations = Annotations::ofMethod($controllerClass, $method->name, '@adminMenu'); | ||
570 | + | ||
571 | + if (!empty($menuAnnotations)) { | ||
572 | + | ||
573 | + $menuAnnotation = $menuAnnotations[0]; | ||
574 | + | ||
575 | + $name = $menuAnnotation->name; | ||
576 | + $icon = $menuAnnotation->icon; | ||
577 | + $type = $menuAnnotation->hasView ? 1 : 2;//1:有界面可访问菜单,2:无界面可访问菜单,0:只作为菜单 | ||
578 | + $action = $method->name; | ||
579 | + $status = empty($menuAnnotation->display) ? 0 : 1; | ||
580 | + $listOrder = floatval($menuAnnotation->order); | ||
581 | + $param = $menuAnnotation->param; | ||
582 | + $remark = $menuAnnotation->remark; | ||
583 | + | ||
584 | + if (empty($menuAnnotation->parent)) { | ||
585 | + $parentId = 0; | ||
586 | + } else { | ||
587 | + $parent = explode('/', $menuAnnotation->parent); | ||
588 | + $countParent = count($parent); | ||
589 | + if ($countParent > 3) { | ||
590 | + throw new \Exception($controllerClass . ':' . $action . ' @menuRoot parent格式不正确!'); | ||
591 | + } | ||
592 | + | ||
593 | + $parentApp = $app; | ||
594 | + $parentController = $controllerName; | ||
595 | + $parentAction = ''; | ||
596 | + | ||
597 | + switch ($countParent) { | ||
598 | + case 1: | ||
599 | + $parentAction = $parent[0]; | ||
600 | + break; | ||
601 | + case 2: | ||
602 | + $parentController = $parent[0]; | ||
603 | + $parentAction = $parent[1]; | ||
604 | + break; | ||
605 | + case 3: | ||
606 | + $parentApp = $parent[0]; | ||
607 | + $parentController = $parent[1]; | ||
608 | + $parentAction = $parent[2]; | ||
609 | + break; | ||
610 | + } | ||
611 | + | ||
612 | + $findParentAdminMenu = Db::name('admin_menu')->where([ | ||
613 | + 'app' => $parentApp, | ||
614 | + 'controller' => $parentController, | ||
615 | + 'action' => $parentAction | ||
616 | + ])->find(); | ||
617 | + | ||
618 | + if (empty($findParentAdminMenu)) { | ||
619 | + $parentId = Db::name('admin_menu')->insertGetId([ | ||
620 | + 'app' => $parentApp, | ||
621 | + 'controller' => $parentController, | ||
622 | + 'action' => $parentAction, | ||
623 | + 'name' => '--new--' | ||
624 | + ]); | ||
625 | + } else { | ||
626 | + $parentId = $findParentAdminMenu['id']; | ||
627 | + } | ||
628 | + } | ||
629 | + | ||
630 | + $findAdminMenu = Db::name('admin_menu')->where([ | ||
631 | + 'app' => $app, | ||
632 | + 'controller' => $controllerName, | ||
633 | + 'action' => $action | ||
634 | + ])->find(); | ||
635 | + | ||
636 | + if (empty($findAdminMenu)) { | ||
637 | + | ||
638 | + Db::name('admin_menu')->insert([ | ||
639 | + 'parent_id' => $parentId, | ||
640 | + 'type' => $type, | ||
641 | + 'status' => $status, | ||
642 | + 'list_order' => $listOrder, | ||
643 | + 'app' => $app, | ||
644 | + 'controller' => $controllerName, | ||
645 | + 'action' => $action, | ||
646 | + 'param' => $param, | ||
647 | + 'name' => $name, | ||
648 | + 'icon' => $icon, | ||
649 | + 'remark' => $remark | ||
650 | + ]); | ||
651 | + | ||
652 | + $menuName = $name; | ||
653 | + | ||
654 | + array_push($newMenus, "$app/$controllerName/$action 已导入"); | ||
655 | + | ||
656 | + } else { | ||
657 | + if ($findAdminMenu['name'] == '--new--') { | ||
658 | + Db::name('admin_menu')->where([ | ||
659 | + 'app' => $app, | ||
660 | + 'controller' => $controllerName, | ||
661 | + 'action' => $action | ||
662 | + ])->update([ | ||
663 | + 'parent_id' => $parentId, | ||
664 | + 'type' => $type, | ||
665 | + 'status' => $status, | ||
666 | + 'list_order' => $listOrder, | ||
667 | + 'param' => $param, | ||
668 | + 'name' => $name, | ||
669 | + 'icon' => $icon, | ||
670 | + 'remark' => $remark | ||
671 | + ]); | ||
672 | + $menuName = $name; | ||
673 | + } else { | ||
674 | + // 只关注菜单层级关系,是否有视图 | ||
675 | + Db::name('admin_menu')->where([ | ||
676 | + 'app' => $app, | ||
677 | + 'controller' => $controllerName, | ||
678 | + 'action' => $action | ||
679 | + ])->update([ | ||
680 | + //'parent_id' => $parentId, | ||
681 | + 'type' => $type, | ||
682 | + ]); | ||
683 | + $menuName = $findAdminMenu['name']; | ||
684 | + } | ||
685 | + | ||
686 | + | ||
687 | + array_push($newMenus, "$app/$controllerName/$action 已更新"); | ||
688 | + } | ||
689 | + | ||
690 | + $authRuleName = "{$app}/{$controllerName}/{$action}"; | ||
691 | + $findAuthRuleCount = Db::name('auth_rule')->where([ | ||
692 | + 'app' => $app, | ||
693 | + 'name' => $authRuleName, | ||
694 | + 'type' => 'admin_url' | ||
695 | + ])->count(); | ||
696 | + | ||
697 | + if ($findAuthRuleCount == 0) { | ||
698 | + Db::name('auth_rule')->insert([ | ||
699 | + 'app' => $app, | ||
700 | + 'name' => $authRuleName, | ||
701 | + 'type' => 'admin_url', | ||
702 | + 'param' => $param, | ||
703 | + 'title' => $menuName | ||
704 | + ]); | ||
705 | + } else { | ||
706 | + Db::name('auth_rule')->where([ | ||
707 | + 'app' => $app, | ||
708 | + 'name' => $authRuleName, | ||
709 | + 'type' => 'admin_url', | ||
710 | + ])->update([ | ||
711 | + 'param' => $param, | ||
712 | + 'title' => $menuName | ||
713 | + ]); | ||
714 | + } | ||
715 | + } | ||
716 | + | ||
717 | + } | ||
718 | + } | ||
719 | + } | ||
720 | + | ||
721 | + } | ||
722 | + } | ||
723 | + | ||
724 | + $index = array_search($app, $apps); | ||
725 | + $nextIndex = $index + 1; | ||
726 | + $nextIndex = $nextIndex >= count($apps) ? 0 : $nextIndex; | ||
727 | + if ($nextIndex) { | ||
728 | + $this->assign("next_app", $apps[$nextIndex]); | ||
729 | + } | ||
730 | + $this->assign("app", $app); | ||
731 | + $this->assign("new_menus", $newMenus); | ||
732 | + | ||
733 | + Cache::clear('admin_menus');// 删除后台菜单缓存 | ||
734 | + | ||
735 | + return $this->fetch(); | ||
736 | + | ||
737 | + } | ||
738 | + | ||
739 | + /** | ||
740 | + * 导出后台菜单语言包 | ||
741 | + * @throws \think\db\exception\DataNotFoundException | ||
742 | + * @throws \think\db\exception\ModelNotFoundException | ||
743 | + * @throws \think\exception\DbException | ||
744 | + */ | ||
745 | + private function _exportAppMenuDefaultLang() | ||
746 | + { | ||
747 | + $menus = Db::name('AdminMenu')->order(["app" => "ASC", "controller" => "ASC", "action" => "ASC"])->select(); | ||
748 | + $langDir = config('DEFAULT_LANG'); | ||
749 | + $adminMenuLang = CMF_ROOT . "data/lang/" . $langDir . "/admin_menu.php"; | ||
750 | + | ||
751 | + if (!empty($adminMenuLang) && !file_exists_case($adminMenuLang)) { | ||
752 | + mkdir(dirname($adminMenuLang), 0777, true); | ||
753 | + } | ||
754 | + | ||
755 | + $lang = []; | ||
756 | + | ||
757 | + foreach ($menus as $menu) { | ||
758 | + $lang_key = strtoupper($menu['app'] . '_' . $menu['controller'] . '_' . $menu['action']); | ||
759 | + $lang[$lang_key] = $menu['name']; | ||
760 | + } | ||
761 | + | ||
762 | + $langStr = var_export($lang, true); | ||
763 | + $langStr = preg_replace("/\s+\d+\s=>\s(\n|\r)/", "\n", $langStr); | ||
764 | + | ||
765 | + if (!empty($adminMenuLang)) { | ||
766 | + file_put_contents($adminMenuLang, "<?php\nreturn $langStr;"); | ||
767 | + } | ||
768 | + } | ||
769 | +} |
app/admin/controller/NavController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: kane <chengjin005@163.com> 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use app\admin\model\NavModel; | ||
15 | +use think\Db; | ||
16 | + | ||
17 | +/** | ||
18 | + * Class NavController 导航类别管理控制器 | ||
19 | + * @package app\admin\controller | ||
20 | + */ | ||
21 | +class NavController extends AdminBaseController | ||
22 | +{ | ||
23 | + /** | ||
24 | + * 导航管理 | ||
25 | + * @adminMenu( | ||
26 | + * 'name' => '导航管理', | ||
27 | + * 'parent' => 'admin/Setting/default', | ||
28 | + * 'display'=> true, | ||
29 | + * 'hasView'=> true, | ||
30 | + * 'order' => 30, | ||
31 | + * 'icon' => '', | ||
32 | + * 'remark' => '导航管理', | ||
33 | + * 'param' => '' | ||
34 | + * ) | ||
35 | + */ | ||
36 | + public function index() | ||
37 | + { | ||
38 | + $content = hook_one('admin_nav_index_view'); | ||
39 | + | ||
40 | + if (!empty($content)) { | ||
41 | + return $content; | ||
42 | + } | ||
43 | + | ||
44 | + $navModel = new NavModel(); | ||
45 | + | ||
46 | + $navs = $navModel->select(); | ||
47 | + $this->assign('navs', $navs); | ||
48 | + | ||
49 | + return $this->fetch(); | ||
50 | + | ||
51 | + } | ||
52 | + | ||
53 | + /** | ||
54 | + * 添加导航 | ||
55 | + * @adminMenu( | ||
56 | + * 'name' => '添加导航', | ||
57 | + * 'parent' => 'index', | ||
58 | + * 'display'=> false, | ||
59 | + * 'hasView'=> true, | ||
60 | + * 'order' => 10000, | ||
61 | + * 'icon' => '', | ||
62 | + * 'remark' => '添加导航', | ||
63 | + * 'param' => '' | ||
64 | + * ) | ||
65 | + */ | ||
66 | + public function add() | ||
67 | + { | ||
68 | + return $this->fetch(); | ||
69 | + } | ||
70 | + | ||
71 | + /** | ||
72 | + * 添加导航提交保存 | ||
73 | + * @adminMenu( | ||
74 | + * 'name' => '添加导航提交保存', | ||
75 | + * 'parent' => 'index', | ||
76 | + * 'display'=> false, | ||
77 | + * 'hasView'=> false, | ||
78 | + * 'order' => 10000, | ||
79 | + * 'icon' => '', | ||
80 | + * 'remark' => '添加导航提交保存', | ||
81 | + * 'param' => '' | ||
82 | + * ) | ||
83 | + */ | ||
84 | + public function addPost() | ||
85 | + { | ||
86 | + | ||
87 | + $navModel = new NavModel(); | ||
88 | + $arrData = $this->request->post(); | ||
89 | + | ||
90 | + if (empty($arrData["is_main"])) { | ||
91 | + $arrData["is_main"] = 0; | ||
92 | + } else { | ||
93 | + $navModel->where("is_main", 1)->update(["is_main" => 0]); | ||
94 | + } | ||
95 | + | ||
96 | + $navModel->allowField(true)->insert($arrData); | ||
97 | + $this->success(lang("EDIT_SUCCESS"), url("nav/index")); | ||
98 | + | ||
99 | + } | ||
100 | + | ||
101 | + /** | ||
102 | + * 编辑导航 | ||
103 | + * @adminMenu( | ||
104 | + * 'name' => '编辑导航', | ||
105 | + * 'parent' => 'index', | ||
106 | + * 'display'=> false, | ||
107 | + * 'hasView'=> true, | ||
108 | + * 'order' => 10000, | ||
109 | + * 'icon' => '', | ||
110 | + * 'remark' => '编辑导航', | ||
111 | + * 'param' => '' | ||
112 | + * ) | ||
113 | + */ | ||
114 | + public function edit() | ||
115 | + { | ||
116 | + $navModel = new NavModel(); | ||
117 | + $intId = $this->request->param("id", 0, 'intval'); | ||
118 | + | ||
119 | + $objNavCat = $navModel->where("id", $intId)->find(); | ||
120 | + $arrNavCat = $objNavCat ? $objNavCat->toArray() : []; | ||
121 | + | ||
122 | + $this->assign($arrNavCat); | ||
123 | + return $this->fetch(); | ||
124 | + } | ||
125 | + | ||
126 | + | ||
127 | + /** | ||
128 | + * 编辑导航提交保存 | ||
129 | + * @adminMenu( | ||
130 | + * 'name' => '编辑导航提交保存', | ||
131 | + * 'parent' => 'index', | ||
132 | + * 'display'=> false, | ||
133 | + * 'hasView'=> false, | ||
134 | + * 'order' => 10000, | ||
135 | + * 'icon' => '', | ||
136 | + * 'remark' => '编辑导航提交保存', | ||
137 | + * 'param' => '' | ||
138 | + * ) | ||
139 | + */ | ||
140 | + public function editPost() | ||
141 | + { | ||
142 | + | ||
143 | + $navModel = new NavModel(); | ||
144 | + $arrData = $this->request->post(); | ||
145 | + | ||
146 | + if (empty($arrData["is_main"])) { | ||
147 | + $arrData["is_main"] = 0; | ||
148 | + } else { | ||
149 | + $navModel->where("is_main", 1)->update(["is_main" => 0]); | ||
150 | + } | ||
151 | + | ||
152 | + $navModel->allowField(true)->where("id", intval($arrData["id"]))->update($arrData); | ||
153 | + $this->success(lang("EDIT_SUCCESS"), url("nav/index")); | ||
154 | + | ||
155 | + } | ||
156 | + | ||
157 | + /** | ||
158 | + * 删除导航 | ||
159 | + * @adminMenu( | ||
160 | + * 'name' => '删除导航', | ||
161 | + * 'parent' => 'index', | ||
162 | + * 'display'=> false, | ||
163 | + * 'hasView'=> false, | ||
164 | + * 'order' => 10000, | ||
165 | + * 'icon' => '', | ||
166 | + * 'remark' => '删除导航', | ||
167 | + * 'param' => '' | ||
168 | + * ) | ||
169 | + */ | ||
170 | + public function delete() | ||
171 | + { | ||
172 | + $navModel = new NavModel(); | ||
173 | + $intId = $this->request->param("id", 0, "intval"); | ||
174 | + | ||
175 | + if (empty($intId)) { | ||
176 | + $this->error(lang("NO_ID")); | ||
177 | + } | ||
178 | + | ||
179 | + $navModel->where("id", $intId)->delete(); | ||
180 | + $this->success(lang("DELETE_SUCCESS"), url("nav/index")); | ||
181 | + | ||
182 | + } | ||
183 | + | ||
184 | + | ||
185 | +} |
app/admin/controller/NavMenuController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: kane <chengjin005@163.com> 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use app\admin\model\NavMenuModel; | ||
14 | +use cmf\controller\AdminBaseController; | ||
15 | +use tree\Tree; | ||
16 | + | ||
17 | +/** | ||
18 | + * Class NavMenuController 前台菜单管理控制器 | ||
19 | + * @package app\admin\controller | ||
20 | + */ | ||
21 | +class NavMenuController extends AdminBaseController | ||
22 | +{ | ||
23 | + /** | ||
24 | + * 导航菜单 | ||
25 | + * @adminMenu( | ||
26 | + * 'name' => '导航菜单', | ||
27 | + * 'parent' => 'admin/Nav/index', | ||
28 | + * 'display'=> false, | ||
29 | + * 'hasView'=> true, | ||
30 | + * 'order' => 10000, | ||
31 | + * 'icon' => '', | ||
32 | + * 'remark' => '导航菜单', | ||
33 | + * 'param' => '' | ||
34 | + * ) | ||
35 | + */ | ||
36 | + public function index() | ||
37 | + { | ||
38 | + $intNavId = $this->request->param("nav_id", 0, 'intval'); | ||
39 | + $navMenuModel = new NavMenuModel(); | ||
40 | + | ||
41 | + if (empty($intNavId)) { | ||
42 | + $this->error("请指定导航!"); | ||
43 | + } | ||
44 | + | ||
45 | + $objResult = $navMenuModel->where("nav_id", $intNavId)->order(["list_order" => "ASC"])->select(); | ||
46 | + $arrResult = $objResult ? $objResult->toArray() : []; | ||
47 | + | ||
48 | + $tree = new Tree(); | ||
49 | + $tree->icon = [' │ ', ' ├─ ', ' └─ ']; | ||
50 | + $tree->nbsp = ' '; | ||
51 | + | ||
52 | + $array = []; | ||
53 | + foreach ($arrResult as $r) { | ||
54 | + $r['str_manage'] = '<a class="btn btn-xs btn-primary" href="' . url("NavMenu/add", ["parent_id" => $r['id'], "nav_id" => $r['nav_id']]) . '">添加子菜单</a> | ||
55 | + <a class="btn btn-xs btn-primary" href="' . url("NavMenu/edit", ["id" => $r['id'], "parent_id" => $r['parent_id'], "nav_id" => $r['nav_id']]) . '">编辑</a> | ||
56 | + <a class="btn btn-xs btn-danger js-ajax-delete" href="' . url("NavMenu/delete", ["id" => $r['id'], 'nav_id' => $r['nav_id']]) . '">删除</a> '; | ||
57 | + $r['status'] = $r['status'] ? "显示" : "隐藏"; | ||
58 | + $array[] = $r; | ||
59 | + } | ||
60 | + | ||
61 | + $tree->init($array); | ||
62 | + $str = "<tr> | ||
63 | + <td><input name='list_orders[\$id]' type='text' size='3' value='\$list_order' class='input input-order'></td> | ||
64 | + <td>\$id</td> | ||
65 | + <td >\$spacer\$name</td> | ||
66 | + <td>\$status</td> | ||
67 | + <td>\$str_manage</td> | ||
68 | + </tr>"; | ||
69 | + | ||
70 | + $categories = $tree->getTree(0, $str); | ||
71 | + | ||
72 | + $this->assign("categories", $categories); | ||
73 | + $this->assign('nav_id', $intNavId); | ||
74 | + | ||
75 | + return $this->fetch(); | ||
76 | + } | ||
77 | + | ||
78 | + /** | ||
79 | + * 添加导航菜单 | ||
80 | + * @adminMenu( | ||
81 | + * 'name' => '添加导航菜单', | ||
82 | + * 'parent' => 'index', | ||
83 | + * 'display'=> false, | ||
84 | + * 'order' => 10000, | ||
85 | + * 'hasView'=> true, | ||
86 | + * 'icon' => '', | ||
87 | + * 'remark' => '添加导航菜单', | ||
88 | + * 'param' => '' | ||
89 | + * ) | ||
90 | + */ | ||
91 | + public function add() | ||
92 | + { | ||
93 | + $navMenuModel = new NavMenuModel(); | ||
94 | + $intNavId = $this->request->param("nav_id", 0, 'intval'); | ||
95 | + $intParentId = $this->request->param("parent_id", 0, 'intval'); | ||
96 | + $objResult = $navMenuModel->where("nav_id", $intNavId)->order(["list_order" => "ASC"])->select(); | ||
97 | + $arrResult = $objResult ? $objResult->toArray() : []; | ||
98 | + | ||
99 | + $tree = new Tree(); | ||
100 | + $tree->icon = [' │ ', ' ├─ ', ' └─ ']; | ||
101 | + $tree->nbsp = ' '; | ||
102 | + $array = []; | ||
103 | + | ||
104 | + foreach ($arrResult as $r) { | ||
105 | + $r['str_manage'] = '<a href="' . url("NavMenu/add", ["parent_id" => $r['id']]) . '">添加子菜单</a> | <a href="' | ||
106 | + . url("NavMenu/edit", ["id" => $r['id']]) . '">编辑</a> | <a class="J_ajax_del" href="' | ||
107 | + . url("NavMenu/delete", ["id" => $r['id']]) . '">删除</a> '; | ||
108 | + $r['status'] = $r['status'] ? "显示" : "隐藏"; | ||
109 | + $r['selected'] = $r['id'] == $intParentId ? "selected" : ""; | ||
110 | + $array[] = $r; | ||
111 | + } | ||
112 | + | ||
113 | + $tree->init($array); | ||
114 | + $str = "<option value='\$id' \$selected>\$spacer\$name</option>"; | ||
115 | + $navTrees = $tree->getTree(0, $str); | ||
116 | + $this->assign("nav_trees", $navTrees); | ||
117 | + | ||
118 | + $navs = $navMenuModel->selectNavs(); | ||
119 | + $this->assign('navs', $navs); | ||
120 | + | ||
121 | + $this->assign("nav_id", $intNavId); | ||
122 | + return $this->fetch(); | ||
123 | + } | ||
124 | + | ||
125 | + /** | ||
126 | + * 添加导航菜单提交保存 | ||
127 | + * @adminMenu( | ||
128 | + * 'name' => '添加导航菜单提交保存', | ||
129 | + * 'parent' => 'index', | ||
130 | + * 'display'=> false, | ||
131 | + * 'hasView'=> false, | ||
132 | + * 'order' => 10000, | ||
133 | + * 'icon' => '', | ||
134 | + * 'remark' => '添加导航菜单提交保存', | ||
135 | + * 'param' => '' | ||
136 | + * ) | ||
137 | + */ | ||
138 | + public function addPost() | ||
139 | + { | ||
140 | + $navMenuModel = new NavMenuModel(); | ||
141 | + $arrData = $this->request->post(); | ||
142 | + | ||
143 | + if (isset($arrData['external_href'])) { | ||
144 | + $arrData['href'] = htmlspecialchars_decode($arrData['external_href']); | ||
145 | + } else { | ||
146 | + $arrData['href'] = htmlspecialchars_decode($arrData['href']); | ||
147 | + $arrData['href'] = base64_decode($arrData['href']); | ||
148 | + } | ||
149 | + | ||
150 | + $navMenuModel->allowField(true)->isUpdate(false)->save($arrData); | ||
151 | + | ||
152 | + $this->success(lang("EDIT_SUCCESS"), url("NavMenu/index", ['nav_id' => $arrData['nav_id']])); | ||
153 | + | ||
154 | + } | ||
155 | + | ||
156 | + /** | ||
157 | + * 编辑导航菜单 | ||
158 | + * @adminMenu( | ||
159 | + * 'name' => '编辑导航菜单', | ||
160 | + * 'parent' => 'index', | ||
161 | + * 'display'=> false, | ||
162 | + * 'hasView'=> true, | ||
163 | + * 'order' => 10000, | ||
164 | + * 'icon' => '', | ||
165 | + * 'remark' => '编辑导航菜单', | ||
166 | + * 'param' => '' | ||
167 | + * ) | ||
168 | + */ | ||
169 | + public function edit() | ||
170 | + { | ||
171 | + $navMenuModel = new NavMenuModel(); | ||
172 | + $intNavId = $this->request->param("nav_id", 0, 'intval'); | ||
173 | + $intId = $this->request->param("id", 0, 'intval'); | ||
174 | + $intParentId = $this->request->param("parent_id", 0, 'intval'); | ||
175 | + $objResult = $navMenuModel | ||
176 | + ->where("nav_id", $intNavId) | ||
177 | + ->where("id", "neq", $intId) | ||
178 | + ->order(["list_order" => "ASC"]) | ||
179 | + ->select(); | ||
180 | + $arrResult = $objResult ? $objResult->toArray() : []; | ||
181 | + | ||
182 | + $tree = new Tree(); | ||
183 | + $tree->icon = [' │ ', ' ├─ ', ' └─ ']; | ||
184 | + $tree->nbsp = ' '; | ||
185 | + $array = []; | ||
186 | + foreach ($arrResult as $r) { | ||
187 | + $r['str_manage'] = '<a href="' . url("NavMenu/add", ["parent_id" => $r['id'], "nav_id" => $intNavId]) . '">添加子菜单</a> | <a href="' | ||
188 | + . url("NavMenu/edit", ["id" => $r['id'], "nav_id" => $intNavId]) . '">编辑</a> | <a class="js-ajax-delete" href="' | ||
189 | + . url("NavMenu/delete", ["id" => $r['id'], "nav_id" => $intNavId]) . '">删除</a> '; | ||
190 | + $r['status'] = $r['status'] ? "显示" : "隐藏"; | ||
191 | + $r['selected'] = $r['id'] == $intParentId ? "selected" : ""; | ||
192 | + $array[] = $r; | ||
193 | + } | ||
194 | + | ||
195 | + $tree->init($array); | ||
196 | + $str = "<option value='\$id' \$selected>\$spacer\$name</option>"; | ||
197 | + $nav_trees = $tree->getTree(0, $str); | ||
198 | + $this->assign("nav_trees", $nav_trees); | ||
199 | + | ||
200 | + $objNav = $navMenuModel->where("id", $intId)->find(); | ||
201 | + $arrNav = $objNav ? $objNav->toArray() : []; | ||
202 | + | ||
203 | + $arrNav['href_old'] = $arrNav['href']; | ||
204 | + | ||
205 | + if (strpos($arrNav['href'], "{") === 0 || $arrNav['href'] == 'home') { | ||
206 | + $arrNav['href'] = base64_encode($arrNav['href']); | ||
207 | + } | ||
208 | + | ||
209 | + $this->assign($arrNav); | ||
210 | + | ||
211 | + $navs = $navMenuModel->selectNavs(); | ||
212 | + $this->assign('navs', $navs); | ||
213 | + | ||
214 | + $this->assign("nav_id", $intNavId); | ||
215 | + $this->assign("parent_id", $intParentId); | ||
216 | + | ||
217 | + return $this->fetch(); | ||
218 | + } | ||
219 | + | ||
220 | + /** | ||
221 | + * 编辑导航菜单提交保存 | ||
222 | + * @adminMenu( | ||
223 | + * 'name' => '编辑导航菜单提交保存', | ||
224 | + * 'parent' => 'index', | ||
225 | + * 'display'=> false, | ||
226 | + * 'hasView'=> false, | ||
227 | + * 'order' => 10000, | ||
228 | + * 'icon' => '', | ||
229 | + * 'remark' => '编辑导航菜单提交保存', | ||
230 | + * 'param' => '' | ||
231 | + * ) | ||
232 | + */ | ||
233 | + public function editPost() | ||
234 | + { | ||
235 | + $navMenuModel = new NavMenuModel(); | ||
236 | + $intId = $this->request->param('id', 0, 'intval'); | ||
237 | + $arrData = $this->request->post(); | ||
238 | + | ||
239 | + if (isset($arrData['external_href'])) { | ||
240 | + $arrData['href'] = htmlspecialchars_decode($arrData['external_href']); | ||
241 | + } else { | ||
242 | + $arrData['href'] = htmlspecialchars_decode($arrData['href']); | ||
243 | + $arrData['href'] = base64_decode($arrData['href']); | ||
244 | + } | ||
245 | + | ||
246 | + $navMenuModel->update($arrData, ["id" => $intId], true); | ||
247 | + | ||
248 | + $this->success(lang("EDIT_SUCCESS"), url("NavMenu/index", ['nav_id' => $arrData['nav_id']])); | ||
249 | + | ||
250 | + } | ||
251 | + | ||
252 | + /** | ||
253 | + * 删除导航菜单 | ||
254 | + * @adminMenu( | ||
255 | + * 'name' => '删除导航菜单', | ||
256 | + * 'parent' => 'index', | ||
257 | + * 'display'=> false, | ||
258 | + * 'hasView'=> false, | ||
259 | + * 'order' => 10000, | ||
260 | + * 'icon' => '', | ||
261 | + * 'remark' => '删除导航菜单', | ||
262 | + * 'param' => '' | ||
263 | + * ) | ||
264 | + */ | ||
265 | + public function delete() | ||
266 | + { | ||
267 | + $navMenuModel = new NavMenuModel(); | ||
268 | + | ||
269 | + $intId = $this->request->param("id", 0, "intval"); | ||
270 | + $intNavId = $this->request->param("nav_id", 0, "intval"); | ||
271 | + | ||
272 | + if (empty($intId)) { | ||
273 | + $this->error(lang("NO_ID")); | ||
274 | + } | ||
275 | + | ||
276 | + $count = $navMenuModel->where("parent_id", $intId)->count(); | ||
277 | + if ($count > 0) { | ||
278 | + $this->error("该菜单下还有子菜单,无法删除!"); | ||
279 | + } | ||
280 | + | ||
281 | + $navMenuModel->where("id", $intId)->delete(); | ||
282 | + $this->success(lang("DELETE_SUCCESS"), url("NavMenu/index", ['nav_id' => $intNavId])); | ||
283 | + | ||
284 | + } | ||
285 | + | ||
286 | + /** | ||
287 | + * 导航菜单排序 | ||
288 | + * @adminMenu( | ||
289 | + * 'name' => '导航菜单排序', | ||
290 | + * 'parent' => 'index', | ||
291 | + * 'display'=> false, | ||
292 | + * 'hasView'=> false, | ||
293 | + * 'order' => 10000, | ||
294 | + * 'icon' => '', | ||
295 | + * 'remark' => '导航菜单排序', | ||
296 | + * 'param' => '' | ||
297 | + * ) | ||
298 | + */ | ||
299 | + public function listOrder() | ||
300 | + { | ||
301 | + $navMenuModel = new NavMenuModel(); | ||
302 | + $status = parent::listOrders($navMenuModel); | ||
303 | + if ($status) { | ||
304 | + $this->success("排序更新成功!"); | ||
305 | + } else { | ||
306 | + $this->error("排序更新失败!"); | ||
307 | + } | ||
308 | + } | ||
309 | + | ||
310 | + | ||
311 | +} |
app/admin/controller/PluginController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <zxxjjforever@163.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use app\admin\model\PluginModel; | ||
15 | +use app\admin\model\HookPluginModel; | ||
16 | +use mindplay\annotations\Annotations; | ||
17 | +use think\Db; | ||
18 | +use think\facade\Cache; | ||
19 | +use think\Validate; | ||
20 | + | ||
21 | +/** | ||
22 | + * Class PluginController | ||
23 | + * @package app\admin\controller | ||
24 | + * @adminMenuRoot( | ||
25 | + * 'name' =>'插件中心', | ||
26 | + * 'action' =>'default', | ||
27 | + * 'parent' =>'', | ||
28 | + * 'display'=> true, | ||
29 | + * 'order' => 20, | ||
30 | + * 'icon' =>'cloud', | ||
31 | + * 'remark' =>'插件中心' | ||
32 | + * ) | ||
33 | + */ | ||
34 | +class PluginController extends AdminBaseController | ||
35 | +{ | ||
36 | + | ||
37 | + protected $pluginModel; | ||
38 | + | ||
39 | + /** | ||
40 | + * 插件列表 | ||
41 | + * @adminMenu( | ||
42 | + * 'name' => '插件列表', | ||
43 | + * 'parent' => 'admin/Plugin/default', | ||
44 | + * 'display'=> true, | ||
45 | + * 'hasView'=> true, | ||
46 | + * 'order' => 10000, | ||
47 | + * 'icon' => '', | ||
48 | + * 'remark' => '插件列表', | ||
49 | + * 'param' => '' | ||
50 | + * ) | ||
51 | + */ | ||
52 | + public function index() | ||
53 | + { | ||
54 | + $pluginModel = new PluginModel(); | ||
55 | + $plugins = $pluginModel->getList(); | ||
56 | + $this->assign("plugins", $plugins); | ||
57 | + return $this->fetch(); | ||
58 | + } | ||
59 | + | ||
60 | + /** | ||
61 | + * 插件启用/禁用 | ||
62 | + * @adminMenu( | ||
63 | + * 'name' => '插件启用禁用', | ||
64 | + * 'parent' => 'index', | ||
65 | + * 'display'=> false, | ||
66 | + * 'hasView'=> false, | ||
67 | + * 'order' => 10000, | ||
68 | + * 'icon' => '', | ||
69 | + * 'remark' => '插件启用禁用', | ||
70 | + * 'param' => '' | ||
71 | + * ) | ||
72 | + */ | ||
73 | + public function toggle() | ||
74 | + { | ||
75 | + $id = $this->request->param('id', 0, 'intval'); | ||
76 | + | ||
77 | + $pluginModel = PluginModel::get($id); | ||
78 | + | ||
79 | + if (empty($pluginModel)) { | ||
80 | + $this->error('插件不存在!'); | ||
81 | + } | ||
82 | + | ||
83 | + $status = 1; | ||
84 | + $successMessage = "启用成功!"; | ||
85 | + | ||
86 | + if ($this->request->param('disable')) { | ||
87 | + $status = 0; | ||
88 | + $successMessage = "禁用成功!"; | ||
89 | + } | ||
90 | + | ||
91 | + $pluginModel->startTrans(); | ||
92 | + | ||
93 | + try { | ||
94 | + $pluginModel->save(['status' => $status], ['id' => $id]); | ||
95 | + | ||
96 | + $hookPluginModel = new HookPluginModel(); | ||
97 | + | ||
98 | + $hookPluginModel->save(['status' => $status], ['plugin' => $pluginModel->name]); | ||
99 | + | ||
100 | + $pluginModel->commit(); | ||
101 | + | ||
102 | + } catch (\Exception $e) { | ||
103 | + | ||
104 | + $pluginModel->rollback(); | ||
105 | + | ||
106 | + $this->error('操作失败!'); | ||
107 | + | ||
108 | + } | ||
109 | + | ||
110 | + Cache::clear('init_hook_plugins'); | ||
111 | + | ||
112 | + $this->success($successMessage); | ||
113 | + } | ||
114 | + | ||
115 | + /** | ||
116 | + * 插件设置 | ||
117 | + * @adminMenu( | ||
118 | + * 'name' => '插件设置', | ||
119 | + * 'parent' => 'index', | ||
120 | + * 'display'=> false, | ||
121 | + * 'hasView'=> true, | ||
122 | + * 'order' => 10000, | ||
123 | + * 'icon' => '', | ||
124 | + * 'remark' => '插件设置', | ||
125 | + * 'param' => '' | ||
126 | + * ) | ||
127 | + */ | ||
128 | + public function setting() | ||
129 | + { | ||
130 | + $id = $this->request->param('id', 0, 'intval'); | ||
131 | + | ||
132 | + $pluginModel = new PluginModel(); | ||
133 | + $plugin = $pluginModel->find($id); | ||
134 | + | ||
135 | + if (empty($plugin)) { | ||
136 | + $this->error('插件未安装!'); | ||
137 | + } | ||
138 | + | ||
139 | + $plugin = $plugin->toArray(); | ||
140 | + | ||
141 | + $pluginClass = cmf_get_plugin_class($plugin['name']); | ||
142 | + if (!class_exists($pluginClass)) { | ||
143 | + $this->error('插件不存在!'); | ||
144 | + } | ||
145 | + | ||
146 | + $pluginObj = new $pluginClass; | ||
147 | + //$plugin['plugin_path'] = $pluginObj->plugin_path; | ||
148 | + //$plugin['custom_config'] = $pluginObj->custom_config; | ||
149 | + $pluginConfigInDb = $plugin['config']; | ||
150 | + $plugin['config'] = include $pluginObj->getConfigFilePath(); | ||
151 | + | ||
152 | + if ($pluginConfigInDb) { | ||
153 | + $pluginConfigInDb = json_decode($pluginConfigInDb, true); | ||
154 | + foreach ($plugin['config'] as $key => $value) { | ||
155 | + if ($value['type'] != 'group') { | ||
156 | + if (isset($pluginConfigInDb[$key])) { | ||
157 | + $plugin['config'][$key]['value'] = $pluginConfigInDb[$key]; | ||
158 | + } | ||
159 | + } else { | ||
160 | + foreach ($value['options'] as $group => $options) { | ||
161 | + foreach ($options['options'] as $gkey => $value) { | ||
162 | + if (isset($pluginConfigInDb[$gkey])) { | ||
163 | + $plugin['config'][$key]['options'][$group]['options'][$gkey]['value'] = $pluginConfigInDb[$gkey]; | ||
164 | + } | ||
165 | + } | ||
166 | + } | ||
167 | + } | ||
168 | + } | ||
169 | + } | ||
170 | + | ||
171 | + $this->assign('data', $plugin); | ||
172 | +// if ($plugin['custom_config']) { | ||
173 | +// $this->assign('custom_config', $this->fetch($plugin['plugin_path'] . $plugin['custom_config'])); | ||
174 | +// } | ||
175 | + | ||
176 | + $this->assign('id', $id); | ||
177 | + return $this->fetch(); | ||
178 | + | ||
179 | + } | ||
180 | + | ||
181 | + /** | ||
182 | + * 插件设置提交 | ||
183 | + * @adminMenu( | ||
184 | + * 'name' => '插件设置提交', | ||
185 | + * 'parent' => 'index', | ||
186 | + * 'display'=> false, | ||
187 | + * 'hasView'=> false, | ||
188 | + * 'order' => 10000, | ||
189 | + * 'icon' => '', | ||
190 | + * 'remark' => '插件设置提交', | ||
191 | + * 'param' => '' | ||
192 | + * ) | ||
193 | + */ | ||
194 | + public function settingPost() | ||
195 | + { | ||
196 | + if ($this->request->isPost()) { | ||
197 | + $id = $this->request->param('id', 0, 'intval'); | ||
198 | + | ||
199 | + $pluginModel = new PluginModel(); | ||
200 | + $plugin = $pluginModel->find($id)->toArray(); | ||
201 | + | ||
202 | + if (!$plugin) { | ||
203 | + $this->error('插件未安装!'); | ||
204 | + } | ||
205 | + | ||
206 | + $pluginClass = cmf_get_plugin_class($plugin['name']); | ||
207 | + if (!class_exists($pluginClass)) { | ||
208 | + $this->error('插件不存在!'); | ||
209 | + } | ||
210 | + | ||
211 | + $pluginObj = new $pluginClass; | ||
212 | + //$plugin['plugin_path'] = $pluginObj->plugin_path; | ||
213 | + //$plugin['custom_config'] = $pluginObj->custom_config; | ||
214 | + $pluginConfigInDb = $plugin['config']; | ||
215 | + $plugin['config'] = include $pluginObj->getConfigFilePath(); | ||
216 | + | ||
217 | + $rules = []; | ||
218 | + $messages = []; | ||
219 | + | ||
220 | + foreach ($plugin['config'] as $key => $value) { | ||
221 | + if ($value['type'] != 'group') { | ||
222 | + if (isset($value['rule'])) { | ||
223 | + $rules[$key] = $this->_parseRules($value['rule']); | ||
224 | + } | ||
225 | + | ||
226 | + if (isset($value['message'])) { | ||
227 | + foreach ($value['message'] as $rule => $msg) { | ||
228 | + $messages[$key . '.' . $rule] = $msg; | ||
229 | + } | ||
230 | + } | ||
231 | + | ||
232 | + } else { | ||
233 | + foreach ($value['options'] as $group => $options) { | ||
234 | + foreach ($options['options'] as $gkey => $value) { | ||
235 | + if (isset($value['rule'])) { | ||
236 | + $rules[$gkey] = $this->_parseRules($value['rule']); | ||
237 | + } | ||
238 | + | ||
239 | + if (isset($value['message'])) { | ||
240 | + foreach ($value['message'] as $rule => $msg) { | ||
241 | + $messages[$gkey . '.' . $rule] = $msg; | ||
242 | + } | ||
243 | + } | ||
244 | + } | ||
245 | + } | ||
246 | + } | ||
247 | + } | ||
248 | + | ||
249 | + $config = $this->request->param('config/a'); | ||
250 | + | ||
251 | + $validate = new Validate($rules, $messages); | ||
252 | + $result = $validate->check($config); | ||
253 | + if ($result !== true) { | ||
254 | + $this->error($validate->getError()); | ||
255 | + } | ||
256 | + | ||
257 | + $pluginModel = new PluginModel(); | ||
258 | + $pluginModel->save(['config' => json_encode($config)], ['id' => $id]); | ||
259 | + $this->success('保存成功', ''); | ||
260 | + } | ||
261 | + } | ||
262 | + | ||
263 | + /** | ||
264 | + * 解析插件配置验证规则 | ||
265 | + * @param $rules | ||
266 | + * @return array | ||
267 | + */ | ||
268 | + private function _parseRules($rules) | ||
269 | + { | ||
270 | + $newRules = []; | ||
271 | + | ||
272 | + $simpleRules = [ | ||
273 | + 'require', 'number', | ||
274 | + 'integer', 'float', 'boolean', 'email', | ||
275 | + 'array', 'accepted', 'date', 'alpha', | ||
276 | + 'alphaNum', 'alphaDash', 'activeUrl', | ||
277 | + 'url', 'ip']; | ||
278 | + foreach ($rules as $key => $rule) { | ||
279 | + if (in_array($key, $simpleRules) && $rule) { | ||
280 | + array_push($newRules, $key); | ||
281 | + } | ||
282 | + } | ||
283 | + | ||
284 | + return $newRules; | ||
285 | + } | ||
286 | + | ||
287 | + /** | ||
288 | + * 插件安装 | ||
289 | + * @adminMenu( | ||
290 | + * 'name' => '插件安装', | ||
291 | + * 'parent' => 'index', | ||
292 | + * 'display'=> false, | ||
293 | + * 'hasView'=> false, | ||
294 | + * 'order' => 10000, | ||
295 | + * 'icon' => '', | ||
296 | + * 'remark' => '插件安装', | ||
297 | + * 'param' => '' | ||
298 | + * ) | ||
299 | + */ | ||
300 | + public function install() | ||
301 | + { | ||
302 | + $pluginName = $this->request->param('name', '', 'trim'); | ||
303 | + $class = cmf_get_plugin_class($pluginName); | ||
304 | + if (!class_exists($class)) { | ||
305 | + $this->error('插件不存在!'); | ||
306 | + } | ||
307 | + | ||
308 | + $pluginModel = new PluginModel(); | ||
309 | + $pluginCount = $pluginModel->where('name', $pluginName)->count(); | ||
310 | + | ||
311 | + if ($pluginCount > 0) { | ||
312 | + $this->error('插件已安装!'); | ||
313 | + } | ||
314 | + | ||
315 | + $plugin = new $class; | ||
316 | + $info = $plugin->info; | ||
317 | + if (!$info || !$plugin->checkInfo()) {//检测信息的正确性 | ||
318 | + $this->error('插件信息缺失!'); | ||
319 | + } | ||
320 | + | ||
321 | + $installSuccess = $plugin->install(); | ||
322 | + if (!$installSuccess) { | ||
323 | + $this->error('插件预安装失败!'); | ||
324 | + } | ||
325 | + | ||
326 | + $methods = get_class_methods($plugin); | ||
327 | + | ||
328 | + foreach ($methods as $methodKey => $method) { | ||
329 | + $methods[$methodKey] = cmf_parse_name($method); | ||
330 | + } | ||
331 | + | ||
332 | + $systemHooks = $pluginModel->getHooks(true); | ||
333 | + | ||
334 | + $pluginHooks = array_intersect($systemHooks, $methods); | ||
335 | + | ||
336 | + //$info['hooks'] = implode(",", $pluginHooks); | ||
337 | + | ||
338 | + if (!empty($plugin->hasAdmin)) { | ||
339 | + $info['has_admin'] = 1; | ||
340 | + } else { | ||
341 | + $info['has_admin'] = 0; | ||
342 | + } | ||
343 | + | ||
344 | + $info['config'] = json_encode($plugin->getConfig()); | ||
345 | + | ||
346 | + $pluginModel->data($info)->allowField(true)->save(); | ||
347 | + | ||
348 | + $hookPluginModel = new HookPluginModel(); | ||
349 | + foreach ($pluginHooks as $pluginHook) { | ||
350 | + $hookPluginModel->data(['hook' => $pluginHook, 'plugin' => $pluginName, 'status' => 1])->isUpdate(false)->save(); | ||
351 | + } | ||
352 | + | ||
353 | + $this->_getActions($pluginName); | ||
354 | + | ||
355 | + Cache::clear('init_hook_plugins'); | ||
356 | + Cache::clear('admin_menus');// 删除后台菜单缓存 | ||
357 | + | ||
358 | + $this->success('安装成功!'); | ||
359 | + } | ||
360 | + | ||
361 | + /** | ||
362 | + * 插件更新 | ||
363 | + * @adminMenu( | ||
364 | + * 'name' => '插件更新', | ||
365 | + * 'parent' => 'index', | ||
366 | + * 'display'=> false, | ||
367 | + * 'hasView'=> false, | ||
368 | + * 'order' => 10000, | ||
369 | + * 'icon' => '', | ||
370 | + * 'remark' => '插件更新', | ||
371 | + * 'param' => '' | ||
372 | + * ) | ||
373 | + */ | ||
374 | + public function update() | ||
375 | + { | ||
376 | + $pluginName = $this->request->param('name', '', 'trim'); | ||
377 | + $class = cmf_get_plugin_class($pluginName); | ||
378 | + if (!class_exists($class)) { | ||
379 | + $this->error('插件不存在!'); | ||
380 | + } | ||
381 | + | ||
382 | + $plugin = new $class; | ||
383 | + $info = $plugin->info; | ||
384 | + if (!$info || !$plugin->checkInfo()) {//检测信息的正确性 | ||
385 | + $this->error('插件信息缺失!'); | ||
386 | + } | ||
387 | + | ||
388 | + $methods = get_class_methods($plugin); | ||
389 | + | ||
390 | + foreach ($methods as $methodKey => $method) { | ||
391 | + $methods[$methodKey] = cmf_parse_name($method); | ||
392 | + } | ||
393 | + | ||
394 | + $pluginModel = new PluginModel(); | ||
395 | + $systemHooks = $pluginModel->getHooks(true); | ||
396 | + | ||
397 | + $pluginHooks = array_intersect($systemHooks, $methods); | ||
398 | + | ||
399 | + if (!empty($plugin->hasAdmin)) { | ||
400 | + $info['has_admin'] = 1; | ||
401 | + } else { | ||
402 | + $info['has_admin'] = 0; | ||
403 | + } | ||
404 | + | ||
405 | + $config = $plugin->getConfig(); | ||
406 | + | ||
407 | + $defaultConfig = $plugin->getDefaultConfig(); | ||
408 | + | ||
409 | + $pluginModel = new PluginModel(); | ||
410 | + | ||
411 | + $config = array_merge($defaultConfig, $config); | ||
412 | + | ||
413 | + $info['config'] = json_encode($config); | ||
414 | + | ||
415 | + $pluginModel->allowField(true)->save($info, ['name' => $pluginName]); | ||
416 | + | ||
417 | + $hookPluginModel = new HookPluginModel(); | ||
418 | + | ||
419 | + $pluginHooksInDb = $hookPluginModel->where('plugin', $pluginName)->column('hook'); | ||
420 | + | ||
421 | + $samePluginHooks = array_intersect($pluginHooks, $pluginHooksInDb); | ||
422 | + | ||
423 | + $shouldDeleteHooks = array_diff($samePluginHooks, $pluginHooksInDb); | ||
424 | + | ||
425 | + $newHooks = array_diff($pluginHooks, $samePluginHooks); | ||
426 | + | ||
427 | + if (count($shouldDeleteHooks) > 0) { | ||
428 | + $hookPluginModel->where('hook', 'in', $shouldDeleteHooks)->delete(); | ||
429 | + } | ||
430 | + | ||
431 | + foreach ($newHooks as $pluginHook) { | ||
432 | + $hookPluginModel->data(['hook' => $pluginHook, 'plugin' => $pluginName])->isUpdate(false)->save(); | ||
433 | + } | ||
434 | + | ||
435 | + $this->_getActions($pluginName); | ||
436 | + | ||
437 | + Cache::clear('init_hook_plugins'); | ||
438 | + Cache::clear('admin_menus');// 删除后台菜单缓存 | ||
439 | + | ||
440 | + $this->success('更新成功!'); | ||
441 | + } | ||
442 | + | ||
443 | + private function _getActions($pluginName) | ||
444 | + { | ||
445 | + Annotations::$config['cache'] = false; | ||
446 | + $annotationManager = Annotations::getManager(); | ||
447 | + $annotationManager->registry['adminMenu'] = 'app\admin\annotation\AdminMenuAnnotation'; | ||
448 | + $annotationManager->registry['adminMenuRoot'] = 'app\admin\annotation\AdminMenuRootAnnotation'; | ||
449 | + $newMenus = []; | ||
450 | + | ||
451 | + $pluginDir = cmf_parse_name($pluginName); | ||
452 | + | ||
453 | + $filePatten = WEB_ROOT . 'plugins/' . $pluginDir . '/controller/Admin*Controller.php'; | ||
454 | + | ||
455 | + $controllers = cmf_scan_dir($filePatten); | ||
456 | + | ||
457 | + $app = 'plugin/' . $pluginName; | ||
458 | + | ||
459 | + if (!empty($controllers)) { | ||
460 | + foreach ($controllers as $controller) { | ||
461 | + $controller = preg_replace('/\.php$/', '', $controller); | ||
462 | + $controllerName = preg_replace('/\Controller$/', '', $controller); | ||
463 | + $controllerClass = "plugins\\$pluginDir\\controller\\$controller"; | ||
464 | + | ||
465 | + $menuAnnotations = Annotations::ofClass($controllerClass, '@adminMenuRoot'); | ||
466 | + | ||
467 | + if (!empty($menuAnnotations)) { | ||
468 | + foreach ($menuAnnotations as $menuAnnotation) { | ||
469 | + | ||
470 | + $name = $menuAnnotation->name; | ||
471 | + $icon = $menuAnnotation->icon; | ||
472 | + $type = 0;//1:有界面可访问菜单,2:无界面可访问菜单,0:只作为菜单 | ||
473 | + $action = $menuAnnotation->action; | ||
474 | + $status = empty($menuAnnotation->display) ? 0 : 1; | ||
475 | + $listOrder = floatval($menuAnnotation->order); | ||
476 | + $param = $menuAnnotation->param; | ||
477 | + $remark = $menuAnnotation->remark; | ||
478 | + | ||
479 | + if (empty($menuAnnotation->parent)) { | ||
480 | + $parentId = 0; | ||
481 | + } else { | ||
482 | + | ||
483 | + $parent = explode('/', $menuAnnotation->parent); | ||
484 | + $countParent = count($parent); | ||
485 | + if ($countParent > 3) { | ||
486 | + throw new \Exception($controllerClass . ':' . $action . ' @adminMenuRoot parent格式不正确!'); | ||
487 | + } | ||
488 | + | ||
489 | + $parentApp = $app; | ||
490 | + $parentController = $controllerName; | ||
491 | + $parentAction = ''; | ||
492 | + | ||
493 | + switch ($countParent) { | ||
494 | + case 1: | ||
495 | + $parentAction = $parent[0]; | ||
496 | + break; | ||
497 | + case 2: | ||
498 | + $parentController = $parent[0]; | ||
499 | + $parentAction = $parent[1]; | ||
500 | + break; | ||
501 | + case 3: | ||
502 | + $parentApp = $parent[0]; | ||
503 | + $parentController = $parent[1]; | ||
504 | + $parentAction = $parent[2]; | ||
505 | + break; | ||
506 | + } | ||
507 | + | ||
508 | + $findParentAdminMenu = Db::name('admin_menu')->where([ | ||
509 | + 'app' => $parentApp, | ||
510 | + 'controller' => $parentController, | ||
511 | + 'action' => $parentAction | ||
512 | + ])->find(); | ||
513 | + | ||
514 | + if (empty($findParentAdminMenu)) { | ||
515 | + $parentId = Db::name('admin_menu')->insertGetId([ | ||
516 | + 'app' => $parentApp, | ||
517 | + 'controller' => $parentController, | ||
518 | + 'action' => $parentAction, | ||
519 | + 'name' => '--new--' | ||
520 | + ]); | ||
521 | + } else { | ||
522 | + $parentId = $findParentAdminMenu['id']; | ||
523 | + } | ||
524 | + } | ||
525 | + | ||
526 | + $findAdminMenu = Db::name('admin_menu')->where([ | ||
527 | + 'app' => $app, | ||
528 | + 'controller' => $controllerName, | ||
529 | + 'action' => $action | ||
530 | + ])->find(); | ||
531 | + | ||
532 | + if (empty($findAdminMenu)) { | ||
533 | + | ||
534 | + Db::name('admin_menu')->insert([ | ||
535 | + 'parent_id' => $parentId, | ||
536 | + 'type' => $type, | ||
537 | + 'status' => $status, | ||
538 | + 'list_order' => $listOrder, | ||
539 | + 'app' => $app, | ||
540 | + 'controller' => $controllerName, | ||
541 | + 'action' => $action, | ||
542 | + 'param' => $param, | ||
543 | + 'name' => $name, | ||
544 | + 'icon' => $icon, | ||
545 | + 'remark' => $remark | ||
546 | + ]); | ||
547 | + | ||
548 | + $menuName = $name; | ||
549 | + | ||
550 | +// array_push($newMenus, $app . "/$controllerName/$action 已导入"); | ||
551 | + | ||
552 | + } else { | ||
553 | + | ||
554 | + if ($findAdminMenu['name'] == '--new--') { | ||
555 | + Db::name('admin_menu')->where([ | ||
556 | + 'app' => $app, | ||
557 | + 'controller' => $controllerName, | ||
558 | + 'action' => $action | ||
559 | + ])->update([ | ||
560 | + 'parent_id' => $parentId, | ||
561 | + 'type' => $type, | ||
562 | + 'status' => $status, | ||
563 | + 'list_order' => $listOrder, | ||
564 | + 'param' => $param, | ||
565 | + 'name' => $name, | ||
566 | + 'icon' => $icon, | ||
567 | + 'remark' => $remark | ||
568 | + ]); | ||
569 | + $menuName = $name; | ||
570 | + } else { | ||
571 | + // 只关注菜单层级关系,是否有视图 | ||
572 | + Db::name('admin_menu')->where([ | ||
573 | + 'app' => $app, | ||
574 | + 'controller' => $controllerName, | ||
575 | + 'action' => $action | ||
576 | + ])->update([ | ||
577 | + //'parent_id' => $parentId, | ||
578 | + 'type' => $type, | ||
579 | + ]); | ||
580 | + $menuName = $findAdminMenu['name']; | ||
581 | + } | ||
582 | + | ||
583 | +// array_push($newMenus, $app."/$controllerName/$action 层级关系已更新"); | ||
584 | + } | ||
585 | + | ||
586 | + $authRuleName = "plugin/{$pluginName}/{$controllerName}/{$action}"; | ||
587 | + $findAuthRuleCount = Db::name('auth_rule')->where([ | ||
588 | + 'app' => $app, | ||
589 | + 'name' => $authRuleName, | ||
590 | + 'type' => 'admin_url' | ||
591 | + ])->count(); | ||
592 | + | ||
593 | + if ($findAuthRuleCount == 0) { | ||
594 | + Db::name('auth_rule')->insert([ | ||
595 | + 'app' => $app, | ||
596 | + 'name' => $authRuleName, | ||
597 | + 'type' => 'admin_url', | ||
598 | + 'param' => $param, | ||
599 | + 'title' => $menuName | ||
600 | + ]); | ||
601 | + } else { | ||
602 | + Db::name('auth_rule')->where([ | ||
603 | + 'app' => $app, | ||
604 | + 'name' => $authRuleName, | ||
605 | + 'type' => 'admin_url', | ||
606 | + ])->update([ | ||
607 | + 'param' => $param, | ||
608 | + 'title' => $menuName | ||
609 | + ]); | ||
610 | + } | ||
611 | + | ||
612 | + } | ||
613 | + } | ||
614 | + | ||
615 | + $reflect = new \ReflectionClass($controllerClass); | ||
616 | + $methods = $reflect->getMethods(\ReflectionMethod::IS_PUBLIC); | ||
617 | + | ||
618 | + if (!empty($methods)) { | ||
619 | + foreach ($methods as $method) { | ||
620 | + | ||
621 | + if ($method->class == $controllerClass && strpos($method->name, '_') !== 0) { | ||
622 | + $menuAnnotations = Annotations::ofMethod($controllerClass, $method->name, '@adminMenu'); | ||
623 | + | ||
624 | + if (!empty($menuAnnotations)) { | ||
625 | + | ||
626 | + $menuAnnotation = $menuAnnotations[0]; | ||
627 | + | ||
628 | + $name = $menuAnnotation->name; | ||
629 | + $icon = $menuAnnotation->icon; | ||
630 | + $type = $menuAnnotation->hasView ? 1 : 2;//1:有界面可访问菜单,2:无界面可访问菜单,0:只作为菜单 | ||
631 | + $action = $method->name; | ||
632 | + $status = empty($menuAnnotation->display) ? 0 : 1; | ||
633 | + $listOrder = floatval($menuAnnotation->order); | ||
634 | + $param = $menuAnnotation->param; | ||
635 | + $remark = $menuAnnotation->remark; | ||
636 | + | ||
637 | + if (empty($menuAnnotation->parent)) { | ||
638 | + $parentId = 0; | ||
639 | + } else { | ||
640 | + $parent = explode('/', $menuAnnotation->parent); | ||
641 | + $countParent = count($parent); | ||
642 | + if ($countParent > 3) { | ||
643 | + throw new \Exception($controllerClass . ':' . $action . ' @menuRoot parent格式不正确!'); | ||
644 | + } | ||
645 | + | ||
646 | + $parentApp = $app; | ||
647 | + $parentController = $controllerName; | ||
648 | + $parentAction = ''; | ||
649 | + | ||
650 | + switch ($countParent) { | ||
651 | + case 1: | ||
652 | + $parentAction = $parent[0]; | ||
653 | + break; | ||
654 | + case 2: | ||
655 | + $parentController = $parent[0]; | ||
656 | + $parentAction = $parent[1]; | ||
657 | + break; | ||
658 | + case 3: | ||
659 | + $parentApp = $parent[0]; | ||
660 | + $parentController = $parent[1]; | ||
661 | + $parentAction = $parent[2]; | ||
662 | + break; | ||
663 | + } | ||
664 | + | ||
665 | + $findParentAdminMenu = Db::name('admin_menu')->where([ | ||
666 | + 'app' => $parentApp, | ||
667 | + 'controller' => $parentController, | ||
668 | + 'action' => $parentAction | ||
669 | + ])->find(); | ||
670 | + | ||
671 | + if (empty($findParentAdminMenu)) { | ||
672 | + $parentId = Db::name('admin_menu')->insertGetId([ | ||
673 | + 'app' => $parentApp, | ||
674 | + 'controller' => $parentController, | ||
675 | + 'action' => $parentAction, | ||
676 | + 'name' => '--new--' | ||
677 | + ]); | ||
678 | + } else { | ||
679 | + $parentId = $findParentAdminMenu['id']; | ||
680 | + } | ||
681 | + } | ||
682 | + | ||
683 | + $findAdminMenu = Db::name('admin_menu')->where([ | ||
684 | + 'app' => $app, | ||
685 | + 'controller' => $controllerName, | ||
686 | + 'action' => $action | ||
687 | + ])->find(); | ||
688 | + | ||
689 | + if (empty($findAdminMenu)) { | ||
690 | + | ||
691 | + Db::name('admin_menu')->insert([ | ||
692 | + 'parent_id' => $parentId, | ||
693 | + 'type' => $type, | ||
694 | + 'status' => $status, | ||
695 | + 'list_order' => $listOrder, | ||
696 | + 'app' => $app, | ||
697 | + 'controller' => $controllerName, | ||
698 | + 'action' => $action, | ||
699 | + 'param' => $param, | ||
700 | + 'name' => $name, | ||
701 | + 'icon' => $icon, | ||
702 | + 'remark' => $remark | ||
703 | + ]); | ||
704 | + | ||
705 | + $menuName = $name; | ||
706 | + | ||
707 | + //array_push($newMenus, "$app/$controllerName/$action 已导入"); | ||
708 | + | ||
709 | + } else { | ||
710 | + if ($findAdminMenu['name'] == '--new--') { | ||
711 | + Db::name('admin_menu')->where([ | ||
712 | + 'app' => $app, | ||
713 | + 'controller' => $controllerName, | ||
714 | + 'action' => $action | ||
715 | + ])->update([ | ||
716 | + 'parent_id' => $parentId, | ||
717 | + 'type' => $type, | ||
718 | + 'status' => $status, | ||
719 | + 'list_order' => $listOrder, | ||
720 | + 'param' => $param, | ||
721 | + 'name' => $name, | ||
722 | + 'icon' => $icon, | ||
723 | + 'remark' => $remark | ||
724 | + ]); | ||
725 | + $menuName = $name; | ||
726 | + } else { | ||
727 | + // 只关注是否有视图 | ||
728 | + Db::name('admin_menu')->where([ | ||
729 | + 'app' => $app, | ||
730 | + 'controller' => $controllerName, | ||
731 | + 'action' => $action | ||
732 | + ])->update([ | ||
733 | + //'parent_id' => $parentId, | ||
734 | + 'type' => $type, | ||
735 | + ]); | ||
736 | + $menuName = $findAdminMenu['name']; | ||
737 | + } | ||
738 | + | ||
739 | + | ||
740 | +// array_push($newMenus, "$app/$controllerName/$action 已更新"); | ||
741 | + } | ||
742 | + | ||
743 | + $authRuleName = "plugin/{$pluginName}/{$controllerName}/{$action}"; | ||
744 | + $findAuthRuleCount = Db::name('auth_rule')->where([ | ||
745 | + 'app' => $app, | ||
746 | + 'name' => $authRuleName, | ||
747 | + 'type' => 'plugin_url' | ||
748 | + ])->count(); | ||
749 | + | ||
750 | + if ($findAuthRuleCount == 0) { | ||
751 | + Db::name('auth_rule')->insert([ | ||
752 | + 'app' => $app, | ||
753 | + 'name' => $authRuleName, | ||
754 | + 'type' => 'plugin_url', | ||
755 | + 'param' => $param, | ||
756 | + 'title' => $menuName | ||
757 | + ]); | ||
758 | + } else { | ||
759 | + Db::name('auth_rule')->where([ | ||
760 | + 'app' => $app, | ||
761 | + 'name' => $authRuleName, | ||
762 | + 'type' => 'plugin_url', | ||
763 | + ])->update([ | ||
764 | + 'param' => $param, | ||
765 | + 'title' => $menuName | ||
766 | + ]); | ||
767 | + } | ||
768 | + } | ||
769 | + | ||
770 | + } | ||
771 | + } | ||
772 | + } | ||
773 | + | ||
774 | + } | ||
775 | + } | ||
776 | + | ||
777 | + } | ||
778 | + | ||
779 | + /** | ||
780 | + * 卸载插件 | ||
781 | + * @adminMenu( | ||
782 | + * 'name' => '卸载插件', | ||
783 | + * 'parent' => 'index', | ||
784 | + * 'display'=> false, | ||
785 | + * 'hasView'=> false, | ||
786 | + * 'order' => 10000, | ||
787 | + * 'icon' => '', | ||
788 | + * 'remark' => '卸载插件', | ||
789 | + * 'param' => '' | ||
790 | + * ) | ||
791 | + */ | ||
792 | + public function uninstall() | ||
793 | + { | ||
794 | + $pluginModel = new PluginModel(); | ||
795 | + $id = $this->request->param('id', 0, 'intval'); | ||
796 | + | ||
797 | + $result = $pluginModel->uninstall($id); | ||
798 | + | ||
799 | + if ($result !== true) { | ||
800 | + $this->error('卸载失败!'); | ||
801 | + } | ||
802 | + | ||
803 | + Cache::clear('init_hook_plugins'); | ||
804 | + Cache::clear('admin_menus');// 删除后台菜单缓存 | ||
805 | + | ||
806 | + $this->success('卸载成功!'); | ||
807 | + } | ||
808 | + | ||
809 | + | ||
810 | +} |
app/admin/controller/PublicController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use think\Db; | ||
15 | + | ||
16 | +class PublicController extends AdminBaseController | ||
17 | +{ | ||
18 | + public function initialize() | ||
19 | + { | ||
20 | + } | ||
21 | + | ||
22 | + /** | ||
23 | + * 后台登陆界面 | ||
24 | + */ | ||
25 | + public function login() | ||
26 | + { | ||
27 | + $loginAllowed = session("__LOGIN_BY_CMF_ADMIN_PW__"); | ||
28 | + if (empty($loginAllowed)) { | ||
29 | + //$this->error('非法登录!', cmf_get_root() . '/'); | ||
30 | + return redirect(cmf_get_root() . "/"); | ||
31 | + } | ||
32 | + | ||
33 | + $admin_id = session('ADMIN_ID'); | ||
34 | + if (!empty($admin_id)) {//已经登录 | ||
35 | + return redirect(url("admin/Index/index")); | ||
36 | + } else { | ||
37 | + session("__SP_ADMIN_LOGIN_PAGE_SHOWED_SUCCESS__", true); | ||
38 | + $result = hook_one('admin_login'); | ||
39 | + if (!empty($result)) { | ||
40 | + return $result; | ||
41 | + } | ||
42 | + return $this->fetch(":login"); | ||
43 | + } | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * 登录验证 | ||
48 | + */ | ||
49 | + public function doLogin() | ||
50 | + { | ||
51 | + if (hook_one('admin_custom_login_open')) { | ||
52 | + $this->error('您已经通过插件自定义后台登录!'); | ||
53 | + } | ||
54 | + | ||
55 | + $loginAllowed = session("__LOGIN_BY_CMF_ADMIN_PW__"); | ||
56 | + if (empty($loginAllowed)) { | ||
57 | + $this->error('非法登录!', cmf_get_root() . '/'); | ||
58 | + } | ||
59 | + | ||
60 | + $captcha = $this->request->param('captcha'); | ||
61 | + if (empty($captcha)) { | ||
62 | + $this->error(lang('CAPTCHA_REQUIRED')); | ||
63 | + } | ||
64 | + //验证码 | ||
65 | + if (!cmf_captcha_check($captcha)) { | ||
66 | + $this->error(lang('CAPTCHA_NOT_RIGHT')); | ||
67 | + } | ||
68 | + | ||
69 | + $name = $this->request->param("username"); | ||
70 | + if (empty($name)) { | ||
71 | + $this->error(lang('USERNAME_OR_EMAIL_EMPTY')); | ||
72 | + } | ||
73 | + $pass = $this->request->param("password"); | ||
74 | + if (empty($pass)) { | ||
75 | + $this->error(lang('PASSWORD_REQUIRED')); | ||
76 | + } | ||
77 | + if (strpos($name, "@") > 0) {//邮箱登陆 | ||
78 | + $where['user_email'] = $name; | ||
79 | + } else { | ||
80 | + $where['user_login'] = $name; | ||
81 | + } | ||
82 | + | ||
83 | + $result = Db::name('user')->where($where)->find(); | ||
84 | + | ||
85 | + if (!empty($result) && $result['user_type'] == 1) { | ||
86 | + if (cmf_compare_password($pass, $result['user_pass'])) { | ||
87 | + $groups = Db::name('RoleUser') | ||
88 | + ->alias("a") | ||
89 | + ->join('__ROLE__ b', 'a.role_id =b.id') | ||
90 | + ->where(["user_id" => $result["id"], "status" => 1]) | ||
91 | + ->value("role_id"); | ||
92 | + if ($result["id"] != 1 && (empty($groups) || empty($result['user_status']))) { | ||
93 | + $this->error(lang('USE_DISABLED')); | ||
94 | + } | ||
95 | + //登入成功页面跳转 | ||
96 | + session('ADMIN_ID', $result["id"]); | ||
97 | + session('name', $result["user_login"]); | ||
98 | + $result['last_login_ip'] = get_client_ip(0, true); | ||
99 | + $result['last_login_time'] = time(); | ||
100 | + $token = cmf_generate_user_token($result["id"], 'web'); | ||
101 | + if (!empty($token)) { | ||
102 | + session('token', $token); | ||
103 | + } | ||
104 | + Db::name('user')->update($result); | ||
105 | + cookie("admin_username", $name, 3600 * 24 * 30); | ||
106 | + session("__LOGIN_BY_CMF_ADMIN_PW__", null); | ||
107 | + $this->success(lang('LOGIN_SUCCESS'), url("admin/Index/index")); | ||
108 | + } else { | ||
109 | + $this->error(lang('PASSWORD_NOT_RIGHT')); | ||
110 | + } | ||
111 | + } else { | ||
112 | + $this->error(lang('USERNAME_NOT_EXIST')); | ||
113 | + } | ||
114 | + } | ||
115 | + | ||
116 | + /** | ||
117 | + * 后台管理员退出 | ||
118 | + */ | ||
119 | + public function logout() | ||
120 | + { | ||
121 | + session('ADMIN_ID', null); | ||
122 | + return redirect(url('/', [], false, true)); | ||
123 | + } | ||
124 | +} |
app/admin/controller/RbacController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use cmf\controller\AdminBaseController; | ||
14 | +use think\Db; | ||
15 | +use think\facade\Cache; | ||
16 | +use tree\Tree; | ||
17 | +use app\admin\model\AdminMenuModel; | ||
18 | + | ||
19 | +class RbacController extends AdminBaseController | ||
20 | +{ | ||
21 | + | ||
22 | + /** | ||
23 | + * 角色管理列表 | ||
24 | + * @adminMenu( | ||
25 | + * 'name' => '角色管理', | ||
26 | + * 'parent' => 'admin/User/default', | ||
27 | + * 'display'=> true, | ||
28 | + * 'hasView'=> true, | ||
29 | + * 'order' => 10000, | ||
30 | + * 'icon' => '', | ||
31 | + * 'remark' => '角色管理', | ||
32 | + * 'param' => '' | ||
33 | + * ) | ||
34 | + * @return mixed | ||
35 | + * @throws \think\db\exception\DataNotFoundException | ||
36 | + * @throws \think\db\exception\ModelNotFoundException | ||
37 | + * @throws \think\exception\DbException | ||
38 | + */ | ||
39 | + public function index() | ||
40 | + { | ||
41 | + $content = hook_one('admin_rbac_index_view'); | ||
42 | + | ||
43 | + if (!empty($content)) { | ||
44 | + return $content; | ||
45 | + } | ||
46 | + | ||
47 | + $data = Db::name('role')->order(["list_order" => "ASC", "id" => "DESC"])->select(); | ||
48 | + $this->assign("roles", $data); | ||
49 | + return $this->fetch(); | ||
50 | + } | ||
51 | + | ||
52 | + /** | ||
53 | + * 添加角色 | ||
54 | + * @adminMenu( | ||
55 | + * 'name' => '添加角色', | ||
56 | + * 'parent' => 'index', | ||
57 | + * 'display'=> false, | ||
58 | + * 'hasView'=> true, | ||
59 | + * 'order' => 10000, | ||
60 | + * 'icon' => '', | ||
61 | + * 'remark' => '添加角色', | ||
62 | + * 'param' => '' | ||
63 | + * ) | ||
64 | + * @return mixed | ||
65 | + */ | ||
66 | + public function roleAdd() | ||
67 | + { | ||
68 | + $content = hook_one('admin_rbac_role_add_view'); | ||
69 | + | ||
70 | + if (!empty($content)) { | ||
71 | + return $content; | ||
72 | + } | ||
73 | + | ||
74 | + return $this->fetch(); | ||
75 | + } | ||
76 | + | ||
77 | + /** | ||
78 | + * 添加角色提交 | ||
79 | + * @adminMenu( | ||
80 | + * 'name' => '添加角色提交', | ||
81 | + * 'parent' => 'index', | ||
82 | + * 'display'=> false, | ||
83 | + * 'hasView'=> false, | ||
84 | + * 'order' => 10000, | ||
85 | + * 'icon' => '', | ||
86 | + * 'remark' => '添加角色提交', | ||
87 | + * 'param' => '' | ||
88 | + * ) | ||
89 | + */ | ||
90 | + public function roleAddPost() | ||
91 | + { | ||
92 | + if ($this->request->isPost()) { | ||
93 | + $data = $this->request->param(); | ||
94 | + $result = $this->validate($data, 'role'); | ||
95 | + if ($result !== true) { | ||
96 | + // 验证失败 输出错误信息 | ||
97 | + $this->error($result); | ||
98 | + } else { | ||
99 | + $result = Db::name('role')->insert($data); | ||
100 | + if ($result) { | ||
101 | + $this->success("添加角色成功", url("rbac/index")); | ||
102 | + } else { | ||
103 | + $this->error("添加角色失败"); | ||
104 | + } | ||
105 | + | ||
106 | + } | ||
107 | + } | ||
108 | + } | ||
109 | + | ||
110 | + /** | ||
111 | + * 编辑角色 | ||
112 | + * @adminMenu( | ||
113 | + * 'name' => '编辑角色', | ||
114 | + * 'parent' => 'index', | ||
115 | + * 'display'=> false, | ||
116 | + * 'hasView'=> true, | ||
117 | + * 'order' => 10000, | ||
118 | + * 'icon' => '', | ||
119 | + * 'remark' => '编辑角色', | ||
120 | + * 'param' => '' | ||
121 | + * ) | ||
122 | + * @return mixed | ||
123 | + * @throws \think\db\exception\DataNotFoundException | ||
124 | + * @throws \think\db\exception\ModelNotFoundException | ||
125 | + * @throws \think\exception\DbException | ||
126 | + */ | ||
127 | + public function roleEdit() | ||
128 | + { | ||
129 | + $content = hook_one('admin_rbac_role_edit_view'); | ||
130 | + | ||
131 | + if (!empty($content)) { | ||
132 | + return $content; | ||
133 | + } | ||
134 | + | ||
135 | + $id = $this->request->param("id", 0, 'intval'); | ||
136 | + if ($id == 1) { | ||
137 | + $this->error("超级管理员角色不能被修改!"); | ||
138 | + } | ||
139 | + $data = Db::name('role')->where("id", $id)->find(); | ||
140 | + if (!$data) { | ||
141 | + $this->error("该角色不存在!"); | ||
142 | + } | ||
143 | + $this->assign("data", $data); | ||
144 | + return $this->fetch(); | ||
145 | + } | ||
146 | + | ||
147 | + /** | ||
148 | + * 编辑角色提交 | ||
149 | + * @adminMenu( | ||
150 | + * 'name' => '编辑角色提交', | ||
151 | + * 'parent' => 'index', | ||
152 | + * 'display'=> false, | ||
153 | + * 'hasView'=> false, | ||
154 | + * 'order' => 10000, | ||
155 | + * 'icon' => '', | ||
156 | + * 'remark' => '编辑角色提交', | ||
157 | + * 'param' => '' | ||
158 | + * ) | ||
159 | + * @throws \think\Exception | ||
160 | + * @throws \think\exception\PDOException | ||
161 | + */ | ||
162 | + public function roleEditPost() | ||
163 | + { | ||
164 | + $id = $this->request->param("id", 0, 'intval'); | ||
165 | + if ($id == 1) { | ||
166 | + $this->error("超级管理员角色不能被修改!"); | ||
167 | + } | ||
168 | + if ($this->request->isPost()) { | ||
169 | + $data = $this->request->param(); | ||
170 | + $result = $this->validate($data, 'role'); | ||
171 | + if ($result !== true) { | ||
172 | + // 验证失败 输出错误信息 | ||
173 | + $this->error($result); | ||
174 | + | ||
175 | + } else { | ||
176 | + if (Db::name('role')->update($data) !== false) { | ||
177 | + $this->success("保存成功!", url('rbac/index')); | ||
178 | + } else { | ||
179 | + $this->error("保存失败!"); | ||
180 | + } | ||
181 | + } | ||
182 | + } | ||
183 | + } | ||
184 | + | ||
185 | + /** | ||
186 | + * 删除角色 | ||
187 | + * @adminMenu( | ||
188 | + * 'name' => '删除角色', | ||
189 | + * 'parent' => 'index', | ||
190 | + * 'display'=> false, | ||
191 | + * 'hasView'=> false, | ||
192 | + * 'order' => 10000, | ||
193 | + * 'icon' => '', | ||
194 | + * 'remark' => '删除角色', | ||
195 | + * 'param' => '' | ||
196 | + * ) | ||
197 | + * @throws \think\Exception | ||
198 | + * @throws \think\exception\PDOException | ||
199 | + */ | ||
200 | + public function roleDelete() | ||
201 | + { | ||
202 | + $id = $this->request->param("id", 0, 'intval'); | ||
203 | + if ($id == 1) { | ||
204 | + $this->error("超级管理员角色不能被删除!"); | ||
205 | + } | ||
206 | + $count = Db::name('RoleUser')->where('role_id', $id)->count(); | ||
207 | + if ($count > 0) { | ||
208 | + $this->error("该角色已经有用户!"); | ||
209 | + } else { | ||
210 | + $status = Db::name('role')->delete($id); | ||
211 | + if (!empty($status)) { | ||
212 | + $this->success("删除成功!", url('rbac/index')); | ||
213 | + } else { | ||
214 | + $this->error("删除失败!"); | ||
215 | + } | ||
216 | + } | ||
217 | + } | ||
218 | + | ||
219 | + /** | ||
220 | + * 设置角色权限 | ||
221 | + * @adminMenu( | ||
222 | + * 'name' => '设置角色权限', | ||
223 | + * 'parent' => 'index', | ||
224 | + * 'display'=> false, | ||
225 | + * 'hasView'=> true, | ||
226 | + * 'order' => 10000, | ||
227 | + * 'icon' => '', | ||
228 | + * 'remark' => '设置角色权限', | ||
229 | + * 'param' => '' | ||
230 | + * ) | ||
231 | + * @return mixed | ||
232 | + */ | ||
233 | + public function authorize() | ||
234 | + { | ||
235 | + $content = hook_one('admin_rbac_authorize_view'); | ||
236 | + | ||
237 | + if (!empty($content)) { | ||
238 | + return $content; | ||
239 | + } | ||
240 | + | ||
241 | + $AuthAccess = Db::name("AuthAccess"); | ||
242 | + $adminMenuModel = new AdminMenuModel(); | ||
243 | + //角色ID | ||
244 | + $roleId = $this->request->param("id", 0, 'intval'); | ||
245 | + if (empty($roleId)) { | ||
246 | + $this->error("参数错误!"); | ||
247 | + } | ||
248 | + | ||
249 | + $tree = new Tree(); | ||
250 | + $tree->icon = ['│ ', '├─ ', '└─ ']; | ||
251 | + $tree->nbsp = ' '; | ||
252 | + | ||
253 | + $result = $adminMenuModel->menuCache(); | ||
254 | + | ||
255 | + $newMenus = []; | ||
256 | + $privilegeData = $AuthAccess->where("role_id", $roleId)->column("rule_name");//获取权限表数据 | ||
257 | + | ||
258 | + foreach ($result as $m) { | ||
259 | + $newMenus[$m['id']] = $m; | ||
260 | + } | ||
261 | + | ||
262 | + foreach ($result as $n => $t) { | ||
263 | + $result[$n]['checked'] = ($this->_isChecked($t, $privilegeData)) ? ' checked' : ''; | ||
264 | + $result[$n]['level'] = $this->_getLevel($t['id'], $newMenus); | ||
265 | + $result[$n]['style'] = empty($t['parent_id']) ? '' : 'display:none;'; | ||
266 | + $result[$n]['parentIdNode'] = ($t['parent_id']) ? ' class="child-of-node-' . $t['parent_id'] . '"' : ''; | ||
267 | + } | ||
268 | + | ||
269 | + $str = "<tr id='node-\$id'\$parentIdNode style='\$style'> | ||
270 | + <td style='padding-left:30px;'>\$spacer<input type='checkbox' name='menuId[]' value='\$id' level='\$level' \$checked onclick='javascript:checknode(this);'> \$name</td> | ||
271 | + </tr>"; | ||
272 | + $tree->init($result); | ||
273 | + | ||
274 | + $category = $tree->getTree(0, $str); | ||
275 | + | ||
276 | + $this->assign("category", $category); | ||
277 | + $this->assign("roleId", $roleId); | ||
278 | + return $this->fetch(); | ||
279 | + } | ||
280 | + | ||
281 | + /** | ||
282 | + * 角色授权提交 | ||
283 | + * @adminMenu( | ||
284 | + * 'name' => '角色授权提交', | ||
285 | + * 'parent' => 'index', | ||
286 | + * 'display'=> false, | ||
287 | + * 'hasView'=> false, | ||
288 | + * 'order' => 10000, | ||
289 | + * 'icon' => '', | ||
290 | + * 'remark' => '角色授权提交', | ||
291 | + * 'param' => '' | ||
292 | + * ) | ||
293 | + * @throws \think\Exception | ||
294 | + * @throws \think\db\exception\DataNotFoundException | ||
295 | + * @throws \think\db\exception\ModelNotFoundException | ||
296 | + * @throws \think\exception\DbException | ||
297 | + * @throws \think\exception\PDOException | ||
298 | + */ | ||
299 | + public function authorizePost() | ||
300 | + { | ||
301 | + if ($this->request->isPost()) { | ||
302 | + $roleId = $this->request->param("roleId", 0, 'intval'); | ||
303 | + if (!$roleId) { | ||
304 | + $this->error("需要授权的角色不存在!"); | ||
305 | + } | ||
306 | + if (is_array($this->request->param('menuId/a')) && count($this->request->param('menuId/a')) > 0) { | ||
307 | + | ||
308 | + Db::name("authAccess")->where(["role_id" => $roleId, 'type' => 'admin_url'])->delete(); | ||
309 | + foreach ($_POST['menuId'] as $menuId) { | ||
310 | + $menu = Db::name("adminMenu")->where("id", $menuId)->field("app,controller,action")->find(); | ||
311 | + if ($menu) { | ||
312 | + $app = $menu['app']; | ||
313 | + $model = $menu['controller']; | ||
314 | + $action = $menu['action']; | ||
315 | + $name = strtolower("$app/$model/$action"); | ||
316 | + Db::name("authAccess")->insert(["role_id" => $roleId, "rule_name" => $name, 'type' => 'admin_url']); | ||
317 | + } | ||
318 | + } | ||
319 | + | ||
320 | + Cache::clear('admin_menus');// 删除后台菜单缓存 | ||
321 | + | ||
322 | + $this->success("授权成功!"); | ||
323 | + } else { | ||
324 | + //当没有数据时,清除当前角色授权 | ||
325 | + Db::name("authAccess")->where("role_id", $roleId)->delete(); | ||
326 | + $this->error("没有接收到数据,执行清除授权成功!"); | ||
327 | + } | ||
328 | + } | ||
329 | + } | ||
330 | + | ||
331 | + /** | ||
332 | + * 检查指定菜单是否有权限 | ||
333 | + * @param array $menu menu表中数组 | ||
334 | + * @param $privData | ||
335 | + * @return bool | ||
336 | + */ | ||
337 | + private function _isChecked($menu, $privData) | ||
338 | + { | ||
339 | + $app = $menu['app']; | ||
340 | + $model = $menu['controller']; | ||
341 | + $action = $menu['action']; | ||
342 | + $name = strtolower("$app/$model/$action"); | ||
343 | + if ($privData) { | ||
344 | + if (in_array($name, $privData)) { | ||
345 | + return true; | ||
346 | + } else { | ||
347 | + return false; | ||
348 | + } | ||
349 | + } else { | ||
350 | + return false; | ||
351 | + } | ||
352 | + | ||
353 | + } | ||
354 | + | ||
355 | + /** | ||
356 | + * 获取菜单深度 | ||
357 | + * @param $id | ||
358 | + * @param array $array | ||
359 | + * @param int $i | ||
360 | + * @return int | ||
361 | + */ | ||
362 | + protected function _getLevel($id, $array = [], $i = 0) | ||
363 | + { | ||
364 | + if ($array[$id]['parent_id'] == 0 || empty($array[$array[$id]['parent_id']]) || $array[$id]['parent_id'] == $id) { | ||
365 | + return $i; | ||
366 | + } else { | ||
367 | + $i++; | ||
368 | + return $this->_getLevel($array[$id]['parent_id'], $array, $i); | ||
369 | + } | ||
370 | + } | ||
371 | + | ||
372 | + //角色成员管理 | ||
373 | + public function member() | ||
374 | + { | ||
375 | + //TODO 添加角色成员管理 | ||
376 | + | ||
377 | + } | ||
378 | + | ||
379 | +} | ||
380 | + |
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 小夏 < 449134904@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use app\admin\model\RecycleBinModel; | ||
14 | +use app\admin\model\RouteModel; | ||
15 | +use cmf\controller\AdminBaseController; | ||
16 | +use think\Db; | ||
17 | + | ||
18 | +class RecycleBinController extends AdminBaseController | ||
19 | +{ | ||
20 | + /** | ||
21 | + * 回收站 | ||
22 | + * @adminMenu( | ||
23 | + * 'name' => '回收站', | ||
24 | + * 'parent' => '', | ||
25 | + * 'display'=> false, | ||
26 | + * 'hasView'=> true, | ||
27 | + * 'order' => 10000, | ||
28 | + * 'icon' => '', | ||
29 | + * 'remark' => '回收站', | ||
30 | + * 'param' => '' | ||
31 | + * ) | ||
32 | + */ | ||
33 | + public function index() | ||
34 | + { | ||
35 | + $content = hook_one('admin_recycle_bin_index_view'); | ||
36 | + | ||
37 | + if (!empty($content)) { | ||
38 | + return $content; | ||
39 | + } | ||
40 | + | ||
41 | + $recycleBinModel = new RecycleBinModel(); | ||
42 | + $list = $recycleBinModel->order('create_time desc')->paginate(10); | ||
43 | + // 获取分页显示 | ||
44 | + $page = $list->render(); | ||
45 | + $this->assign('page', $page); | ||
46 | + $this->assign('list', $list); | ||
47 | + return $this->fetch(); | ||
48 | + } | ||
49 | + | ||
50 | + /** | ||
51 | + * 回收站还原 | ||
52 | + * @adminMenu( | ||
53 | + * 'name' => '回收站还原', | ||
54 | + * 'parent' => 'index', | ||
55 | + * 'display'=> false, | ||
56 | + * 'hasView'=> false, | ||
57 | + * 'order' => 10000, | ||
58 | + * 'icon' => '', | ||
59 | + * 'remark' => '回收站还原', | ||
60 | + * 'param' => '' | ||
61 | + * ) | ||
62 | + */ | ||
63 | + public function restore() | ||
64 | + { | ||
65 | + | ||
66 | + $id = $this->request->param('id', 0, 'intval'); | ||
67 | + $result = Db::name('recycleBin')->where('id', $id)->find(); | ||
68 | + | ||
69 | + $tableName = explode('#', $result['table_name']); | ||
70 | + $tableName = $tableName[0]; | ||
71 | + //还原资源 | ||
72 | + if ($result) { | ||
73 | + $res = Db::name($tableName) | ||
74 | + ->where('id', $result['object_id']) | ||
75 | + ->update(['delete_time' => '0']); | ||
76 | + if ($tableName == 'portal_post') { | ||
77 | + Db::name('portal_category_post')->where('post_id', $result['object_id'])->update(['status' => 1]); | ||
78 | + Db::name('portal_tag_post')->where('post_id', $result['object_id'])->update(['status' => 1]); | ||
79 | + } | ||
80 | + | ||
81 | + if ($res) { | ||
82 | + $re = Db::name('recycleBin')->where('id', $id)->delete(); | ||
83 | + if ($re) { | ||
84 | + $this->success("还原成功!"); | ||
85 | + } | ||
86 | + } | ||
87 | + } | ||
88 | + } | ||
89 | + | ||
90 | + /** | ||
91 | + * 回收站彻底删除 | ||
92 | + * @adminMenu( | ||
93 | + * 'name' => '回收站彻底删除', | ||
94 | + * 'parent' => 'index', | ||
95 | + * 'display'=> false, | ||
96 | + * 'hasView'=> false, | ||
97 | + * 'order' => 10000, | ||
98 | + * 'icon' => '', | ||
99 | + * 'remark' => '回收站彻底删除', | ||
100 | + * 'param' => '' | ||
101 | + * ) | ||
102 | + */ | ||
103 | + public function delete() | ||
104 | + { | ||
105 | + $id = $this->request->param('id'); | ||
106 | + $result = Db::name('recycleBin')->where('id', $id)->find(); | ||
107 | + //删除资源 | ||
108 | + if ($result) { | ||
109 | + | ||
110 | + //页面没有单独的表. | ||
111 | + if ($result['table_name'] === 'portal_post#page') { | ||
112 | + $re = Db::name('portal_post')->where('id', $result['object_id'])->delete(); | ||
113 | + //消除路由 | ||
114 | + $routeModel = new RouteModel(); | ||
115 | + $routeModel->setRoute('', 'portal/Page/index', ['id' => $result['object_id']], 2, 5000); | ||
116 | + $routeModel->getRoutes(true); | ||
117 | + } else { | ||
118 | + $re = Db::name($result['table_name'])->where('id', $result['object_id'])->delete(); | ||
119 | + } | ||
120 | + | ||
121 | + if ($re) { | ||
122 | + $res = Db::name('recycleBin')->where('id', $id)->delete(); | ||
123 | + if ($result['table_name'] === 'portal_post') { | ||
124 | + Db::name('portal_category_post')->where('post_id', $result['object_id'])->delete(); | ||
125 | + Db::name('portal_tag_post')->where('post_id', $result['object_id'])->delete(); | ||
126 | + } | ||
127 | + if ($res) { | ||
128 | + $this->success("删除成功!"); | ||
129 | + } | ||
130 | + | ||
131 | + } | ||
132 | + } | ||
133 | + } | ||
134 | +} |
app/admin/controller/RouteController.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: 老猫 <thinkcmf@126.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | +namespace app\admin\controller; | ||
12 | + | ||
13 | +use app\admin\model\RouteModel; | ||
14 | +use cmf\controller\AdminBaseController; | ||
15 | +use think\Db; | ||
16 | + | ||
17 | +class RouteController extends AdminBaseController | ||
18 | +{ | ||
19 | + | ||
20 | + /** | ||
21 | + * 路由规则列表 | ||
22 | + * @adminMenu( | ||
23 | + * 'name' => 'URL美化', | ||
24 | + * 'parent' => 'admin/Setting/default', | ||
25 | + * 'display'=> true, | ||
26 | + * 'hasView'=> true, | ||
27 | + * 'order' => 10000, | ||
28 | + * 'icon' => '', | ||
29 | + * 'remark' => 'URL规则管理', | ||
30 | + * 'param' => '' | ||
31 | + * ) | ||
32 | + */ | ||
33 | + public function index() | ||
34 | + { | ||
35 | + global $CMF_GV_routes; | ||
36 | + $routeModel = new RouteModel(); | ||
37 | + $routes = Db::name('route')->order("list_order asc")->select(); | ||
38 | + $routeModel->getRoutes(true); | ||
39 | + unset($CMF_GV_routes); | ||
40 | + $this->assign("routes", $routes); | ||
41 | + return $this->fetch(); | ||
42 | + } | ||
43 | + | ||
44 | + /** | ||
45 | + * 添加路由规则 | ||
46 | + * @adminMenu( | ||
47 | + * 'name' => '添加路由规则', | ||
48 | + * 'parent' => 'index', | ||
49 | + * 'display'=> false, | ||
50 | + * 'hasView'=> true, | ||
51 | + * 'order' => 10000, | ||
52 | + * 'icon' => '', | ||
53 | + * 'remark' => '添加路由规则', | ||
54 | + * 'param' => '' | ||
55 | + * ) | ||
56 | + */ | ||
57 | + public function add() | ||
58 | + { | ||
59 | + return $this->fetch(); | ||
60 | + } | ||
61 | + | ||
62 | + /** | ||
63 | + * 添加路由规则提交 | ||
64 | + * @adminMenu( | ||
65 | + * 'name' => '添加路由规则提交', | ||
66 | + * 'parent' => 'index', | ||
67 | + * 'display'=> false, | ||
68 | + * 'hasView'=> false, | ||
69 | + * 'order' => 10000, | ||
70 | + * 'icon' => '', | ||
71 | + * 'remark' => '添加路由规则提交', | ||
72 | + * 'param' => '' | ||
73 | + * ) | ||
74 | + */ | ||
75 | + public function addPost() | ||
76 | + { | ||
77 | + $data = $this->request->param(); | ||
78 | + $routeModel = new RouteModel(); | ||
79 | + $result = $this->validate($data, 'Route'); | ||
80 | + if ($result !== true) { | ||
81 | + $this->error($result); | ||
82 | + } | ||
83 | + $routeModel->allowField(true)->save($data); | ||
84 | + | ||
85 | + $this->success("添加成功!", url("Route/index", ['id' => $routeModel->id])); | ||
86 | + } | ||
87 | + | ||
88 | + /** | ||
89 | + * 路由规则编辑 | ||
90 | + * @adminMenu( | ||
91 | + * 'name' => '路由规则编辑', | ||
92 | + * 'parent' => 'index', | ||
93 | + * 'display'=> false, | ||
94 | + * 'hasView'=> true, | ||
95 | + * 'order' => 10000, | ||
96 | + * 'icon' => '', | ||
97 | + * 'remark' => '路由规则编辑', | ||
98 | + * 'param' => '' | ||
99 | + * ) | ||
100 | + */ | ||
101 | + public function edit() | ||
102 | + { | ||
103 | + $id = $this->request->param("id", 0, 'intval'); | ||
104 | + $route = Db::name('route')->where('id', $id)->find(); | ||
105 | + $this->assign($route); | ||
106 | + return $this->fetch(); | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * 路由规则编辑提交 | ||
111 | + * @adminMenu( | ||
112 | + * 'name' => '路由规则编辑提交', | ||
113 | + * 'parent' => 'index', | ||
114 | + * 'display'=> false, | ||
115 | + * 'hasView'=> false, | ||
116 | + * 'order' => 10000, | ||
117 | + * 'icon' => '', | ||
118 | + * 'remark' => '路由规则编辑提交', | ||
119 | + * 'param' => '' | ||
120 | + * ) | ||
121 | + */ | ||
122 | + public function editPost() | ||
123 | + { | ||
124 | + $data = $this->request->param(); | ||
125 | + $routeModel = new RouteModel(); | ||
126 | + $result = $this->validate($data, 'Route'); | ||
127 | + if ($result !== true) { | ||
128 | + $this->error($result); | ||
129 | + } | ||
130 | + $routeModel->allowField(true)->isUpdate(true)->save($data); | ||
131 | + | ||
132 | + $this->success("保存成功!", url("Route/index")); | ||
133 | + } | ||
134 | + | ||
135 | + /** | ||
136 | + * 路由规则删除 | ||
137 | + * @adminMenu( | ||
138 | + * 'name' => '路由规则删除', | ||
139 | + * 'parent' => 'index', | ||
140 | + * 'display'=> false, | ||
141 | + * 'hasView'=> false, | ||
142 | + * 'order' => 10000, | ||
143 | + * 'icon' => '', | ||
144 | + * 'remark' => '路由规则删除', | ||
145 | + * 'param' => '' | ||
146 | + * ) | ||
147 | + */ | ||
148 | + public function delete() | ||
149 | + { | ||
150 | + $id = $this->request->param('id', 0, 'intval'); | ||
151 | + RouteModel::destroy($id); | ||
152 | + | ||
153 | + $this->success("删除成功!"); | ||
154 | + } | ||
155 | + | ||
156 | + /** | ||
157 | + * 路由规则禁用 | ||
158 | + * @adminMenu( | ||
159 | + * 'name' => '路由规则禁用', | ||
160 | + * 'parent' => 'index', | ||
161 | + * 'display'=> false, | ||
162 | + * 'hasView'=> false, | ||
163 | + * 'order' => 10000, | ||
164 | + * 'icon' => '', | ||
165 | + * 'remark' => '路由规则禁用', | ||
166 | + * 'param' => '' | ||
167 | + * ) | ||
168 | + */ | ||
169 | + public function ban() | ||
170 | + { | ||
171 | + $id = $this->request->param("id", 0, 'intval'); | ||
172 | + $data = []; | ||
173 | + $data['status'] = 0; | ||
174 | + $data['id'] = $id; | ||
175 | + $routeModel = new RouteModel(); | ||
176 | + | ||
177 | + $routeModel->isUpdate(true)->save($data); | ||
178 | + $this->success("禁用成功!"); | ||
179 | + } | ||
180 | + | ||
181 | + /** | ||
182 | + * 路由规则启用 | ||
183 | + * @adminMenu( | ||
184 | + * 'name' => '路由规则启用', | ||
185 | + * 'parent' => 'index', | ||
186 | + * 'display'=> false, | ||
187 | + * 'hasView'=> false, | ||
188 | + * 'order' => 10000, | ||
189 | + * 'icon' => '', | ||
190 | + * 'remark' => '路由规则启用', | ||
191 | + * 'param' => '' | ||
192 | + * ) | ||
193 | + */ | ||
194 | + public function open() | ||
195 | + { | ||
196 | + $id = $this->request->param("id", 0, 'intval'); | ||
197 | + $data = []; | ||
198 | + $data['status'] = 1; | ||
199 | + $data['id'] = $id; | ||
200 | + $routeModel = new RouteModel(); | ||
201 | + | ||
202 | + $routeModel->isUpdate(true)->save($data); | ||
203 | + $this->success("启用成功!"); | ||
204 | + } | ||
205 | + | ||
206 | + /** | ||
207 | + * 路由规则排序 | ||
208 | + * @adminMenu( | ||
209 | + * 'name' => '路由规则排序', | ||
210 | + * 'parent' => 'index', | ||
211 | + * 'display'=> false, | ||
212 | + * 'hasView'=> false, | ||
213 | + * 'order' => 10000, | ||
214 | + * 'icon' => '', | ||
215 | + * 'remark' => '路由规则排序', | ||
216 | + * 'param' => '' | ||
217 | + * ) | ||
218 | + */ | ||
219 | + public function listOrder() | ||
220 | + { | ||
221 | + $routeModel = new RouteModel(); | ||
222 | + parent::listOrders($routeModel); | ||
223 | + $this->success("排序更新成功!"); | ||
224 | + } | ||
225 | + | ||
226 | + /** | ||
227 | + * 选择 URL | ||
228 | + * @adminMenu( | ||
229 | + * 'name' => '选择URL', | ||
230 | + * 'parent' => 'index', | ||
231 | + * 'display'=> false, | ||
232 | + * 'hasView'=> true, | ||
233 | + * 'order' => 10000, | ||
234 | + * 'icon' => '', | ||
235 | + * 'remark' => '选择URL', | ||
236 | + * 'param' => '' | ||
237 | + * ) | ||
238 | + */ | ||
239 | + public function select() | ||
240 | + { | ||
241 | + $routeModel = new RouteModel(); | ||
242 | + $urls = $routeModel->getAppUrls(); | ||
243 | + | ||
244 | + $this->assign('urls', $urls); | ||
245 | + return $this->fetch(); | ||
246 | + } | ||
247 | + | ||
248 | + function _suggest_url($action, $url) | ||
249 | + { | ||
250 | + $actionArr = explode('/', $action); | ||
251 | + | ||
252 | + $params = array_keys($url['vars']); | ||
253 | + | ||
254 | + $urlDepr1Params = []; | ||
255 | + | ||
256 | + $urlDepr2Params = []; | ||
257 | + | ||
258 | + if (!empty($params)) { | ||
259 | + | ||
260 | + foreach ($params as $param) { | ||
261 | + if (empty($url['vars'][$param]['require'])) { | ||
262 | + array_push($urlDepr1Params, "[:$param]"); | ||
263 | + } else { | ||
264 | + array_push($urlDepr1Params, ":$param"); | ||
265 | + } | ||
266 | + | ||
267 | + array_push($urlDepr2Params, htmlspecialchars('<') . $param . htmlspecialchars('>')); | ||
268 | + } | ||
269 | + | ||
270 | + } | ||
271 | + | ||
272 | + if ($actionArr[2] == 'index') { | ||
273 | + $actionArr[1] = cmf_parse_name($actionArr[1]); | ||
274 | + return empty($params) ? $actionArr[1] . '$' : ($actionArr[1] . '/' . implode('/', $urlDepr1Params) /*. '或' . $actionArr[1] . '-' . implode('-', $urlDepr2Params)*/); | ||
275 | + } else { | ||
276 | + $actionArr[2] = cmf_parse_name($actionArr[2]); | ||
277 | + return empty($params) ? $actionArr[2] . '$' : ($actionArr[2] . '/' . implode('/', $urlDepr1Params) /*. '或' . $actionArr[2] . '-' . implode('-', $urlDepr2Params)*/); | ||
278 | + } | ||
279 | + | ||
280 | + } | ||
281 | + | ||
282 | + function _url_vars($url) | ||
283 | + { | ||
284 | + if (!empty($url['vars'])) { | ||
285 | + return implode(',', array_keys($url['vars'])); | ||
286 | + } | ||
287 | + | ||
288 | + return ''; | ||
289 | + } | ||
290 | + | ||
291 | +} |
-
请 注册 或 登录 后发表评论