代码
This commit is contained in:
commit
d49c9fde59
838
CHANGELOG.md
Normal file
838
CHANGELOG.md
Normal file
@ -0,0 +1,838 @@
|
|||||||
|
|
||||||
|
## V5.1.34 LTS(2019-1-30)
|
||||||
|
|
||||||
|
本次更新为常规更新,修正了一些反馈的问题。
|
||||||
|
|
||||||
|
* 改进Request类的`has`方法,支持`patch`
|
||||||
|
* 改进`unique`验证的多条件支持
|
||||||
|
* 修复自定义上传验证,检测文件大小
|
||||||
|
* 改进`in`查询支持表达式
|
||||||
|
* 改进路由的`getBind`方法
|
||||||
|
* 改进验证类的错误信息获取
|
||||||
|
* 改进`response`助手函数默认值
|
||||||
|
* 修正mysql的`regexp`查询
|
||||||
|
* 改进模型类型强制转换写入对`Expression`对象的支持
|
||||||
|
|
||||||
|
## V5.1.33 LTS(2019-1-16)
|
||||||
|
|
||||||
|
* 修复路由中存在多个相同替换的正则BUG
|
||||||
|
* 修正whereLike查询
|
||||||
|
* join方法支持参数绑定
|
||||||
|
* 改进union方法
|
||||||
|
* 修正多对多关联的attach方法
|
||||||
|
* 改进验证类的正则规则自定义
|
||||||
|
* 改进Request类method方法
|
||||||
|
* 改进File日志类型的CLI日志写入
|
||||||
|
* 改进文件日志time_format配置对JSON格式的支持
|
||||||
|
|
||||||
|
## V5.1.32 LTS(2018-12-24)
|
||||||
|
|
||||||
|
本次主要为常规更新,修正了一些反馈的问题。
|
||||||
|
|
||||||
|
|
||||||
|
* 改进多对多关联的`attach`方法
|
||||||
|
* 改进聚合查询的`field`处理
|
||||||
|
* 改进关联的`save`方法
|
||||||
|
* 修正模型`exists`方法返回值
|
||||||
|
* 改进时间字段写入和输出
|
||||||
|
* 改进控制器中间件的调用
|
||||||
|
* 改进路由变量替换的性能
|
||||||
|
* 改进缓存标签的处理机制
|
||||||
|
|
||||||
|
## V5.1.31 LTS (2018-12-9)
|
||||||
|
|
||||||
|
本次版本包含一个安全更新,建议升级。
|
||||||
|
|
||||||
|
* 改进`field`方法
|
||||||
|
* 改进`count`方法返回类型
|
||||||
|
* `download`函数增加在浏览器中显示文件功能
|
||||||
|
* 修正多对多模型的中间表数据写入
|
||||||
|
* 改进`sqlsrv`驱动支持多个Schemas模式查询
|
||||||
|
* 统一助手函数与\think\response\Download函数文件过期时间
|
||||||
|
* 完善关联模型的`save`方法 增加`make`方法仅创建对象不保存
|
||||||
|
* 修改条件表达式对静态变量的支持
|
||||||
|
* 修正控制器名获取
|
||||||
|
* 改进view方法的`field`解析
|
||||||
|
|
||||||
|
## V5.1.30 LTS(2018-11-30)
|
||||||
|
|
||||||
|
该版本为常规更新,修正了一些社区反馈的问题。
|
||||||
|
|
||||||
|
主要更新如下:
|
||||||
|
|
||||||
|
* 改进查询类的`execute`方法
|
||||||
|
* 判断路由规则定义添加对请求类型的判断
|
||||||
|
* 修复`orderRaw`异常
|
||||||
|
* 修正 `optimize:autoload`指令
|
||||||
|
* 改进软删除的`destroy`方法造成重复执行事件的问题
|
||||||
|
* 改进验证类对扩展验证规则 始终验证 不管是否`require`
|
||||||
|
* 修复自定义验证`remove`所有规则的异常
|
||||||
|
* 改进时间字段的自动写入支持微秒数据
|
||||||
|
* 改进`Connection`类的`getrealsql`方法
|
||||||
|
* 修正`https`地址的URL生成
|
||||||
|
* 修复 `array_walk_recursive` 在低于PHP7.1消耗内部指针问题
|
||||||
|
* 改进手动参数绑定使用
|
||||||
|
* 改进聚合查询方法的`field`参数支持`Expression`
|
||||||
|
|
||||||
|
## V5.1.29 LTS(2018-11-11)
|
||||||
|
|
||||||
|
该版本主要改进了参数绑定的解析问题和提升性能,并修正了一些反馈的问题。
|
||||||
|
|
||||||
|
* 改进手动参数绑定
|
||||||
|
* 修正MISS路由的分组参数无效问题
|
||||||
|
* 行为支持对象的方法
|
||||||
|
* 修正全局查询范围
|
||||||
|
* 改进`belongsto`关联的`has`方法
|
||||||
|
* 改进`hasMany`关联
|
||||||
|
* 改进模型观察者多次注册的问题
|
||||||
|
* 改进`query`类的默认查询参数处理
|
||||||
|
* 修正`parseBetween`解析方法
|
||||||
|
* 改进路由地址生成的本地域名支持
|
||||||
|
* 改进参数绑定的实际URL解析性能
|
||||||
|
* 改进`Env`类的`getEnv`和`get`方法
|
||||||
|
* 改进模板缓存的生成优化
|
||||||
|
* 修复验证类的多语言支持
|
||||||
|
* 修复自定义场景验证`remove`规则异常
|
||||||
|
* File类添加是否自动补全扩展名的选项
|
||||||
|
* 改进`strpos`对子串是否存在的判断
|
||||||
|
* 修复`choice`无法用值选择第一个选项问题
|
||||||
|
* 验证器支持多维数组取值验证
|
||||||
|
* 改进解析`extend`和`block`标签的正则
|
||||||
|
|
||||||
|
## V5.1.28 LTS(2018-10-29)
|
||||||
|
|
||||||
|
该版本主要修正了上一个版本存在的一些问题,并改进了关联查询
|
||||||
|
|
||||||
|
* 改进聚合查询方法的字段支持DISTINCT
|
||||||
|
* 改进定义路由后url函数的端口生成
|
||||||
|
* 改进控制器中间件对`swoole`等的支持
|
||||||
|
* 改进Log类`save`方法
|
||||||
|
* 改进验证类的闭包验证参数
|
||||||
|
* 多对多关联支持指定中间表数据的名称
|
||||||
|
* 关联聚合查询支持闭包方式指定聚合字段
|
||||||
|
* 改进Lang类`get`方法
|
||||||
|
* 多对多关联增加判断关联数据是否存在的方法
|
||||||
|
* 改进关联查询使用`fetchsql`的情况
|
||||||
|
* 改进修改器的是否已经执行判断
|
||||||
|
* 增加`afterWith`和`beforeWith`验证规则 用于比较日期字段
|
||||||
|
|
||||||
|
## V5.1.27 LTS(2018-10-22)
|
||||||
|
|
||||||
|
该版本主要修正了路由绑定的参数,改进了修改器的执行多次问题,并正式宣布为LTS版本!
|
||||||
|
|
||||||
|
|
||||||
|
* 修正路由绑定的参数丢失问题
|
||||||
|
* 修正路由别名的参数获取
|
||||||
|
* 改进修改器会执行多次的问题
|
||||||
|
|
||||||
|
## V5.1.26(2018-10-12)
|
||||||
|
|
||||||
|
该版本主要修正了上一个版本的一些问题,并改进了全局查询范围的支持,同时包含了一个安全更新。
|
||||||
|
|
||||||
|
|
||||||
|
* 修正单一模块下注解路由无效的问题
|
||||||
|
* 改进数据库的聚合查询的字段处理
|
||||||
|
* 模型类增加`globalScope`属性定义 用于指定全局的查询范围
|
||||||
|
* 模型的`useGlobalScope`方法支持传入数组 用于指定当前查询需要使用的全局查询范围
|
||||||
|
* 改进数据集的`order`方法对数字类型的支持
|
||||||
|
* 修正上一个版本`order`方法解析的一处BUG
|
||||||
|
* 排序字段不合法或者错误的时候抛出异常
|
||||||
|
* 改进`Request`类的`file`方法对上传文件的错误判断
|
||||||
|
|
||||||
|
## V5.1.25(2018-9-21)
|
||||||
|
|
||||||
|
该版本主要改进了查询参数绑定的性能和对浮点型的支持,以及一些细节的完善。
|
||||||
|
|
||||||
|
* 修正一处命令行问题
|
||||||
|
* 改进`Socketlog`日志驱动,支持自定义默认展开日志类别
|
||||||
|
* 修正`MorphMany`一处bug
|
||||||
|
* 跳转到上次记住的url,并支持默认值
|
||||||
|
* 改进模型的异常提示
|
||||||
|
* 改进参数绑定对浮点型的支持
|
||||||
|
* 改进`order`方法解析
|
||||||
|
* 改进`json`字段数据的自动编码
|
||||||
|
* 改进日志`log_write`可能造成的日志写入死循环
|
||||||
|
* Log类增加`log_level`行为标签位置,用于对某个类型的日志进行处理
|
||||||
|
* Route类增加`clear`方法清空路由规则
|
||||||
|
* 分布式数据库配置支持使用数组
|
||||||
|
* 单日志文件也支持`max_files`参数
|
||||||
|
* 改进查询参数绑定的性能
|
||||||
|
* 改进别名路由的URL后缀参数检测
|
||||||
|
* 控制器前置方法和控制器中间件的`only`和`except`定义不区分大小写
|
||||||
|
|
||||||
|
## V5.1.24(2018-9-5)
|
||||||
|
|
||||||
|
该版本主要增加了命令行的表格输出功能,并增加了查看路由定义的指令,以及修正了社区的一些反馈问题。
|
||||||
|
|
||||||
|
* 修正`Request`类的`file`方法
|
||||||
|
* 修正路由的`cache`方法
|
||||||
|
* 修正路由缓存的一处问题
|
||||||
|
* 改进上传文件获取的异常处理
|
||||||
|
* 改进`fetchCollection`方法支持传入数据集类名
|
||||||
|
* 修正多级控制器的注解路由生成
|
||||||
|
* 改进`Middleware`类`clear`方法
|
||||||
|
* 增加`route:list`指令用于[查看定义的路由](752690) 并支持排序
|
||||||
|
* 命令行增加`Table`输出类
|
||||||
|
* `Command`类增加`table`方法用于输出表格
|
||||||
|
* 改进搜索器查询方法支持别名定义
|
||||||
|
* 命令行配置增加`auto_path`参数用于定义自动载入的命令类路径
|
||||||
|
* 增加`make:command`指令用于[快速生成指令](354146)
|
||||||
|
* 改进`make:controller`指令对操作方法后缀的支持
|
||||||
|
* 改进命令行的定义文件支持索引数组 用于指令对象的惰性加载
|
||||||
|
* 改进`value`和`column`方法对后续查询结果的影响
|
||||||
|
* 改进`RuleName`类的`setRule`方法
|
||||||
|
|
||||||
|
## V5.1.23(2018-8-23)
|
||||||
|
|
||||||
|
该版本主要改进了数据集对象的处理,增加了`findOrEmpty`方法,并且修正了一些社区反馈的BUG。
|
||||||
|
|
||||||
|
* 数据集类增加`diff`/`intersect`方法用于获取差集和交集(默认根据主键值比较)
|
||||||
|
* 数据集类增加`order`方法支持指定字段排序
|
||||||
|
* 数据集类增加`map`方法使用回调函数处理数据并返回新的数据集对象
|
||||||
|
* Db增加`allowEmpty`方法允许`find`方法在没有数据的时候返回空数组或者空模型对象而不是null
|
||||||
|
* Db增加`findOrEmpty`方法
|
||||||
|
* Db增加`fetchCollection`方法用于指定查询返回数据集对象
|
||||||
|
* 改进`order`方法的数组方式解析,增强安全性
|
||||||
|
* 改进`withSearch`方法,支持第三个参数传入字段前缀标识,用于多表查询字段搜索
|
||||||
|
* 修正`optimize:route`指令开启类库后缀后的注解路由生成
|
||||||
|
* 修正redis缓存及session驱动
|
||||||
|
* 支持指定`Yaconf`的独立配置文件
|
||||||
|
* 增加`yaconf`助手函数用于配置文件
|
||||||
|
|
||||||
|
|
||||||
|
## V5.1.22(2018-8-9)
|
||||||
|
|
||||||
|
该版本主要增加了模型搜索器和`withJoin`方法,完善了模型输出和对`Yaconf`的支持,修正了一些社区反馈的BUG。
|
||||||
|
|
||||||
|
* 改进一对一关联的`table`识别问题
|
||||||
|
* 改进内置`Facade`类
|
||||||
|
* 增加`withJoin`方法支持`join`方式的[一对一关联](一对一关联.md)查询
|
||||||
|
* 改进`join`预载入查询的空数据问题
|
||||||
|
* 改进`Config`类的`load`方法支持快速加载配置文件
|
||||||
|
* 改进`execute`方法和事务的断线重连
|
||||||
|
* 改进`memcache`驱动的`has`方法
|
||||||
|
* 模型类支持定义[搜索器](搜索器.md)方法
|
||||||
|
* 完善`Config`类对`Yaconf`的支持
|
||||||
|
* 改进模型的`hidden/visible/append/withAttr`方法,支持在[查询前后调用](数组访问.md),以及支持数据集对象
|
||||||
|
* 数据集对象增加`where`方法根据字段或者关联数据[过滤数据](模型数据集.md)
|
||||||
|
* 改进AJAX请求的`204`判断
|
||||||
|
|
||||||
|
|
||||||
|
## V5.1.21(2018-8-2)
|
||||||
|
|
||||||
|
该版本主要增加了下载响应对象和数组查询对象的支持,并修正了一些社区反馈的问题。
|
||||||
|
|
||||||
|
* 改进核心对象的无用信息调试输出
|
||||||
|
* 改进模型的`isRelationAttr`方法判断
|
||||||
|
* 模型类的`get`和`all`方法并入Db类
|
||||||
|
* 增加[下载响应对象](文件下载.md)和`download`助手函数
|
||||||
|
* 修正别名路由配置定义读取
|
||||||
|
* 改进`resultToModel`方法
|
||||||
|
* 修正开启类库后缀后的注解路由生成
|
||||||
|
* `Response`类增加`noCache`快捷方法
|
||||||
|
* 改进路由对象在`Swoole`/`Workerman`下面参数多次合并问题
|
||||||
|
* 修正路由`ajax`/`pjax`参数后路由变量无法正确获取的问题
|
||||||
|
* 增加清除中间件的方法
|
||||||
|
* 改进依赖注入的参数规范自动识别(便于对接前端小写+下划线规范)
|
||||||
|
* 改进`hasWhere`的数组条件的字段判断
|
||||||
|
* 增加[数组查询对象](高级查询.md)`Where`支持(喜欢数组查询的福音)
|
||||||
|
* 改进多对多关联的闭包支持
|
||||||
|
|
||||||
|
## V5.1.20(2018-7-25)
|
||||||
|
|
||||||
|
该版本主要增加了Db和模型的动态获取器的支持,并修正了一些已知问题。
|
||||||
|
|
||||||
|
* Db类添加[获取器支持](703981)
|
||||||
|
* 支持模型及关联模型字段[动态定义获取器](354046)
|
||||||
|
* 动态获取器支持`JSON`字段
|
||||||
|
* 改进路由的`before`行为执行(匹配后执行)
|
||||||
|
* `Config`类支持`Yaconf`
|
||||||
|
* 改进Url生成的端口问题
|
||||||
|
* Request类增加`setUrl`和`setBaseUrl`方法
|
||||||
|
* 改进页面trace的信息显示
|
||||||
|
* 修正`MorphOne`关联
|
||||||
|
* 命令行添加[查看版本指令](703994)
|
||||||
|
|
||||||
|
## V5.1.19 (2018-7-13)
|
||||||
|
|
||||||
|
该版本是一个小幅改进版本,针对`Swoole`和`Workerman`的`Cookie`支持做了一些改进,并修正了一些已知的问题。
|
||||||
|
|
||||||
|
|
||||||
|
* 改进query类`delete`方法对软删除条件判断
|
||||||
|
* 修正分表查询的软删除问题
|
||||||
|
* 模型查询的时候同时传入`table`和`name`属性
|
||||||
|
* 容器类增加`IteratorAggregate`和`Countable`接口支持
|
||||||
|
* 路由分组支持对下面的资源路由统一设置`only/except/vars`参数
|
||||||
|
* 改进Cookie类更好支持扩展
|
||||||
|
* 改进Request类`post`方法
|
||||||
|
* 改进模型自关联的自动识别
|
||||||
|
* 改进Request类对`php://input`数据的处理
|
||||||
|
|
||||||
|
|
||||||
|
## V5.1.18 (2018-6-30)
|
||||||
|
|
||||||
|
该版本主要完善了对`Swoole`和`Workerman`的`HttpServer`运行支持,改进`Request`类,并修正了一些已知的问题。
|
||||||
|
|
||||||
|
* 改进关联`append`方法的处理
|
||||||
|
* 路由初始化和检测方法分离
|
||||||
|
* 修正`destroy`方法强制删除
|
||||||
|
* `app_init`钩子位置移入`run`方法
|
||||||
|
* `think-swoole`扩展更新到2.0版本
|
||||||
|
* `think-worker`扩展更新到2.0版本
|
||||||
|
* 改进Url生成的域名自动识别
|
||||||
|
* `Request`类增加`setPathinfo`方法和`setHost`方法
|
||||||
|
* `Request`类增加`withGet`/`withPost`/`withHeader`/`withServer`/`withCookie`/`withEnv`方法进行赋值操作
|
||||||
|
* Route类改进`host`属性的获取
|
||||||
|
* 解决注解路由配置不生效的问题
|
||||||
|
* 取消Test日志驱动,改为使用`close`设置关闭全局日志写入
|
||||||
|
* 修正路由的`response`参数
|
||||||
|
* 修正204响应输出的判断
|
||||||
|
|
||||||
|
## V5.1.17 (2018-6-18)
|
||||||
|
|
||||||
|
该版本主要增加了控制器中间件的支持,改进了路由功能,并且修正了社区反馈的一些问题。
|
||||||
|
|
||||||
|
* 修正软删除的`delete`方法
|
||||||
|
* 修正Query类`Count`方法
|
||||||
|
* 改进多对多`detach`方法
|
||||||
|
* 改进Request类`Session`方法
|
||||||
|
* 增加控制器中间件支持
|
||||||
|
* 模型类增加`jsonAssoc`属性用于定义json数据是否返回数组
|
||||||
|
* 修正Request类`method`方法的请求伪装
|
||||||
|
* 改进静态路由的匹配
|
||||||
|
* 分组首页路由自动完整匹配
|
||||||
|
* 改进sqlsrv的`column`方法
|
||||||
|
* 日志类的`apart_level`配置支持true自动生成对应类型的日志文件
|
||||||
|
* 改进`204`输出判断
|
||||||
|
* 修正cli下页面输出的BUG
|
||||||
|
* 验证类使用更高效的`ctype`验证机制
|
||||||
|
* 改进Request类`cookie`方法
|
||||||
|
* 修正软删除的`withTrashed`方法
|
||||||
|
* 改进多态一对多的预载入查询
|
||||||
|
* 改进Query类`column`方法的缓存读取
|
||||||
|
* Query类增加`whereBetweenTimeField`方法
|
||||||
|
* 改进分组下多个相同路由规则的合并匹配问题
|
||||||
|
* 路由类增加`getRule`/`getRuleList`方法获取定义的路由
|
||||||
|
|
||||||
|
## V5.1.16 (2018-6-7)
|
||||||
|
|
||||||
|
该版本主要修正了社区反馈的一些问题,并对Request类做了进一步规范和优化。
|
||||||
|
|
||||||
|
* 改进Session类的`boot`方法
|
||||||
|
* App类的初始化方法可以单独执行
|
||||||
|
* 改进Request类的`param`方法
|
||||||
|
* 改进资源路由的变量替换
|
||||||
|
* Request类增加`__isset`方法
|
||||||
|
* 改进`useGlobalScope`方法对软删除的影响
|
||||||
|
* 修正命令行调用
|
||||||
|
* 改进Cookie类`init`方法
|
||||||
|
* 改进多对多关联删除的返回值
|
||||||
|
* 一对多关联写入支持`replace`
|
||||||
|
* 路由增加`filter`检测方法,用于通过请求参数检测路由是否匹配
|
||||||
|
* 取消Request类`session/env/server`方法的`filter`参数
|
||||||
|
* 改进关联的指定属性输出
|
||||||
|
* 模型删除操作删除后不清空对象数据仅作标记
|
||||||
|
* 调整模型的`save`方法返回值为布尔值
|
||||||
|
* 修正Request类`isAjax`方法
|
||||||
|
* 修正中间件的模块配置读取
|
||||||
|
* 取消Request类的请求变量的设置功能
|
||||||
|
* 取消请求变量获取的默认修饰符
|
||||||
|
* Request类增加`setAction/setModule/setController`方法
|
||||||
|
* 关联模型的`delete`方法调用Query类
|
||||||
|
* 改进URL生成的域名识别
|
||||||
|
* 改进URL检测对已定义路由的域名判断
|
||||||
|
* 模型类增加`isExists`和`isForce`方法
|
||||||
|
* 软删除的`destroy`和`restore`方法返回值调整为布尔值
|
||||||
|
|
||||||
|
## V5.1.15 (2018-6-1)
|
||||||
|
|
||||||
|
该版本主要改进了路由缓存的性能和缓存方式设置,增加了JSON格式文件日志的支持,并修正了社区反馈的一些问题。
|
||||||
|
|
||||||
|
* 容器类增加`exists`方法 仅判断是否存在对象实例
|
||||||
|
* 取消配置类的`autoload`方法
|
||||||
|
* 改进路由缓存大小提高性能
|
||||||
|
* 改进Dispatch类`init`方法
|
||||||
|
* 增加`make:validate`指令生成验证器类
|
||||||
|
* Config类`get`方法支持默认值参数
|
||||||
|
* 修正字段缓存指令
|
||||||
|
* 改进App类对`null`数据的返回
|
||||||
|
* 改进模型类的`__isset`方法判断
|
||||||
|
* 修正`Query`类的`withAggregate`方法
|
||||||
|
* 改进`RuleItem`类的`setRuleName`方法
|
||||||
|
* 修正依赖注入和参数的冲突问题
|
||||||
|
* 修正Db类对第三方驱动的支持
|
||||||
|
* 修正模型类查询对象问题
|
||||||
|
* 修正File缓存驱动的`has`方法
|
||||||
|
* 修正资源路由嵌套
|
||||||
|
* 改进Request类对`$_SERVER`变量的读取
|
||||||
|
* 改进请求缓存处理
|
||||||
|
* 路由缓存支持指定单独的缓存方式和参数
|
||||||
|
* 修正资源路由的中间件多次执行问题
|
||||||
|
* 修正`optimize:config`指令
|
||||||
|
* 文件日志支持`JSON`格式日志保存
|
||||||
|
* 修正Db类`connect`方法
|
||||||
|
* 改进Log类`write`方法不会自动写入之前日志
|
||||||
|
* 模型的关联操作默认启用事务
|
||||||
|
* 改进软删除的事件响应
|
||||||
|
|
||||||
|
## V5.1.14 (2018-5-18)
|
||||||
|
|
||||||
|
该版本主要对底层容器进行了一些优化改进,并增加了路由缓存功能,可以进一步提升路由性能。
|
||||||
|
|
||||||
|
* 依赖注入的对象参数传入改进
|
||||||
|
* 改进核心类的容器实例化
|
||||||
|
* 改进日期字段的读取
|
||||||
|
* 改进验证类的`getScene`方法
|
||||||
|
* 模型的`create`方法和`save`方法支持`replace`操作
|
||||||
|
* 改进`Db`类的调用机制
|
||||||
|
* App类调整为容器类
|
||||||
|
* 改进容器默认绑定
|
||||||
|
* `Loader`类增加工厂类的实例化方法
|
||||||
|
* 增加路由变量默认规则配置参数
|
||||||
|
* 增加路由缓存设计
|
||||||
|
* 错误处理机制改进
|
||||||
|
* 增加清空路由缓存指令
|
||||||
|
|
||||||
|
|
||||||
|
## V5.1.13 (2018-5-11)
|
||||||
|
|
||||||
|
该版本主要增加了MySQL的XA事务支持,模型事件支持观察者,以及对Facade类的改进。
|
||||||
|
|
||||||
|
* 改进自动缓存
|
||||||
|
* 改进Url生成
|
||||||
|
* 修正数据缓存
|
||||||
|
* 修正`value`方法的缓存
|
||||||
|
* `join`方法和`view`方法的条件支持使用`Expression`对象
|
||||||
|
* 改进驱动的`parseKey`方法
|
||||||
|
* 改进Request类`host`方法和`domain`方法对端口的处理
|
||||||
|
* 模型增加`withEvent`方法用于控制当前操作是否需要执行模型事件
|
||||||
|
* 模型`setInc/setDec`方法支持更新事件
|
||||||
|
* 模型添加`before_restore/after_restore`事件
|
||||||
|
* 增加模型事件观察者
|
||||||
|
* 路由增加`mobile`方法设置是否允许手机访问
|
||||||
|
* 数据库XA事务支持
|
||||||
|
* 改进索引数组查询对`IN`查询的支持
|
||||||
|
* 修正`invokeMethod`方法
|
||||||
|
* 修正空数据写入返回值的BUG
|
||||||
|
* redis驱动支持`predis`
|
||||||
|
* 改进`parseData`方法
|
||||||
|
* 改进模块加载
|
||||||
|
* App类初始化方法调整
|
||||||
|
* 改进数组查询对表达式`Expression`对象支持
|
||||||
|
* 改进闭包的依赖注入调用
|
||||||
|
* 改进多对多关联的中间表模型更新
|
||||||
|
* 增加容器中对象的自定义实例化
|
||||||
|
|
||||||
|
## V5.1.12 (2018-4-25)
|
||||||
|
|
||||||
|
该版本主要改进了主从查询的及时性,并支持动态设置请求数据。
|
||||||
|
|
||||||
|
* 支持动态设置请求数据
|
||||||
|
* 改进`comment`方法解析
|
||||||
|
* 修正App类`__unset`方法
|
||||||
|
* 改进url生成的域名绑定
|
||||||
|
* 改进主从查询的及时性
|
||||||
|
* 修正`value`的数据缓存功能
|
||||||
|
* 改进分页类的集合对象方法调用
|
||||||
|
* 改进Db类的代码提示
|
||||||
|
* SQL日志增加主从标记
|
||||||
|
|
||||||
|
## V5.1.11 (2018-4-19)
|
||||||
|
|
||||||
|
该版本为安全和修正版本,改进了JSON查询的参数绑定问题和容器类对象实例获取,并包含一处可能的安全隐患,建议更新。
|
||||||
|
|
||||||
|
* 支持指定JSON数据查询的字段类型
|
||||||
|
* 修正`selectInsert`方法
|
||||||
|
* `whereColumn`方法支持数组方式
|
||||||
|
* 改进容器类`make`方法
|
||||||
|
* 容器类`delete`方法支持数组
|
||||||
|
* 改进`composer`自动加载
|
||||||
|
* 改进模板引擎
|
||||||
|
* 修正`like`查询的一处安全隐患
|
||||||
|
|
||||||
|
## V5.1.10 (2018-4-16)
|
||||||
|
|
||||||
|
该版本为修正版本,修正上一个版本的一些BUG,并增强了`think clear`指令。
|
||||||
|
|
||||||
|
* 改进`orderField`方法
|
||||||
|
* 改进`exists`查询
|
||||||
|
* 修改cli模式入口文件位置计算
|
||||||
|
* 修正`null`查询
|
||||||
|
* 改进`parseTime`方法
|
||||||
|
* 修正关联预载入查询
|
||||||
|
* 改进`mysql`驱动
|
||||||
|
* 改进`think clear`指令 支持 `-c -l -r `选项
|
||||||
|
* 改进路由规则对`/`结尾的支持
|
||||||
|
|
||||||
|
## V5.1.9 (2018-4-12)
|
||||||
|
|
||||||
|
该版本主要是一些改进和修正,并包含一个安全更新,是一个推荐更新版本。
|
||||||
|
|
||||||
|
* 默认模板渲染规则支持配置保持操作方法名
|
||||||
|
* 改进`Request`类的`ip`方法
|
||||||
|
* 支持模型软删除字段的默认值定义
|
||||||
|
* 改进路由变量规则对中文的支持
|
||||||
|
* 使用闭包查询的时候使用`cache(true)` 抛出异常提示
|
||||||
|
* 改进`Loader`类`loadComposerAutoloadFiles`方法
|
||||||
|
* 改进查询方法安全性
|
||||||
|
* 修正路由地址中控制器名驼峰问题
|
||||||
|
* 调整上一个版本的`module_init`和`app_begin`的钩子顺序问题
|
||||||
|
* 改进CLI命令行执行的问题
|
||||||
|
* 修正社区反馈的其它问题
|
||||||
|
|
||||||
|
## V5.1.8 (2018-4-5)
|
||||||
|
|
||||||
|
该版本主要改进了中间件的域名和模块支持,并同时修正了几个已知问题。
|
||||||
|
|
||||||
|
* 增加`template.auto_rule` 参数设置默认模板渲染的操作名自动转换规则
|
||||||
|
* 默认模板渲染规则改由视图驱动实现
|
||||||
|
* 修正路由标识定义
|
||||||
|
* 修正控制器路由方法
|
||||||
|
* 改进Request类`ip`方法支持自定义代理IP参数
|
||||||
|
* 路由注册中间件支持数组方式别名
|
||||||
|
* 改进命令行执行下的`composer`自动加载
|
||||||
|
* 添加域名中间件注册支持
|
||||||
|
* 全局中间件支持模块定义文件
|
||||||
|
* Log日志配置支持`close`参数可以全局关闭日志写入
|
||||||
|
* 中间件方法中捕获`HttpResponseException`异常
|
||||||
|
* 改进中间件的闭包参数传入
|
||||||
|
* 改进分组路由的延迟解析
|
||||||
|
* 改进URL生成对域名绑定的支持
|
||||||
|
* 改进文件缓存和文件日志驱动的并发支持
|
||||||
|
|
||||||
|
## V5.1.7 (2018-3-28)
|
||||||
|
|
||||||
|
该版本主要修正了路由的一些问题,并改进了查询的安全性。
|
||||||
|
|
||||||
|
* 支持`middleware`配置文件预先定义中间件别名方便路由调用
|
||||||
|
* 修正资源路由
|
||||||
|
* 改进`field`方法 自动识别`fieldRaw`
|
||||||
|
* 增加`Expression`类
|
||||||
|
* Query类增加`raw`方法
|
||||||
|
* Query类的`field`/ `order` 和` where`方法都支持使用`raw`表达式查询
|
||||||
|
* 改进`inc/dec`查询 支持批量更新
|
||||||
|
* 改进路由分组
|
||||||
|
* 改进Response类`create`方法
|
||||||
|
* 改进composer自动加载
|
||||||
|
* 修正域名路由的`append`方法
|
||||||
|
* 修正操作方法的初始化方法获取不到问题
|
||||||
|
|
||||||
|
## V5.1.6 (2018-3-26)
|
||||||
|
|
||||||
|
该版本主要改进了路由规则的匹配算法,大幅提升了路由性能。并正式引入了中间件的支持,可以在路由中定义或者全局定义。另外包含了一个安全更新,是一个建议更新版本。
|
||||||
|
|
||||||
|
* 改进URL生成对路由`ext`方法的支持
|
||||||
|
* 改进查询缓存对不同数据库相同表名的支持
|
||||||
|
* 改进composer自动加载的性能
|
||||||
|
* 改进空路由变量对默认参数的影响
|
||||||
|
* mysql的`json`字段查询支持多级
|
||||||
|
* Query类增加`option`方法
|
||||||
|
* 优化路由匹配
|
||||||
|
* 修复验证规则数字键名丢失问题
|
||||||
|
* 改进路由Url生成
|
||||||
|
* 改进一对一关联预载入查询
|
||||||
|
* Request类增加`rootDomain`方法
|
||||||
|
* 支持API资源控制器生成 `make:controller --api`
|
||||||
|
* 优化Template类的标签解析
|
||||||
|
* 容器类增加删除和清除对象实例的方法
|
||||||
|
* 修正MorphMany关联的`eagerlyMorphToMany`方法一处错误
|
||||||
|
* Container类的异常捕获改进
|
||||||
|
* Domain对象支持`bind`方法
|
||||||
|
* 修正分页参数
|
||||||
|
* 默认模板的输出规则不受URL影响
|
||||||
|
* 注解路由支持多级控制器
|
||||||
|
* Query类增加`getNumRows`方法获取前次操作影响的记录数
|
||||||
|
* 改进查询条件的性能
|
||||||
|
* 改进模型类`readTransform`方法对序列化类型的处理
|
||||||
|
* Log类增加`close`方法可以临时关闭当前请求的日志写入
|
||||||
|
* 文件日志方式增加自动清理功能(设置`max_files`参数)
|
||||||
|
* 修正Query类的`getPk`方法
|
||||||
|
* 修正模板缓存的布局开关问题
|
||||||
|
* 修正Query类`select`方法的缓存
|
||||||
|
* 改进input助手函数
|
||||||
|
* 改进断线重连的信息判断
|
||||||
|
* 改进正则验证方法
|
||||||
|
* 调整语言包的加载顺序 放到`app_init`之前
|
||||||
|
* controller类`fetch`方法改为`final`
|
||||||
|
* 路由地址中的变量支持使用`<var>`方式
|
||||||
|
* 改进XMLResponse 支持传入编码过的xml内容
|
||||||
|
* 修正Query类`view`方法的数组表名支持
|
||||||
|
* 改进路由的模型闭包绑定
|
||||||
|
* 改进分组变量规则的继承
|
||||||
|
* 改进`cli-server`模式下的`composer`自动加载
|
||||||
|
* 路由变量规则异常捕获
|
||||||
|
* 引入中间件支持
|
||||||
|
* 路由定义增加`middleware`方法
|
||||||
|
* 增加生成中间件指令`make:middleware`
|
||||||
|
* 增加全局中间件定义支持
|
||||||
|
* 改进`optimize:config`指令对全局中间件的支持
|
||||||
|
* 改进config类`has`方法
|
||||||
|
* 改进时间查询的参数绑定
|
||||||
|
* 改进`inc/dec/exp`查询的安全性
|
||||||
|
|
||||||
|
|
||||||
|
## V5.1.5 (2018-1-31)
|
||||||
|
|
||||||
|
该版本主要增强了数据库的JSON查询,并支持JSON字段的聚合查询,改进了一些性能问题,修正了路由的一些BUG,主要更新如下:
|
||||||
|
|
||||||
|
* 改进数据集查询对`JSON`数据的支持
|
||||||
|
* 改进聚合查询对`JSON`字段的支持
|
||||||
|
* 模型类增加`getOrFail`方法
|
||||||
|
* 改进数据库驱动的`parseKey`方法
|
||||||
|
* 改进Query类`join`方法的自关联查询
|
||||||
|
* 改进数据查询不存在不生成查询缓存
|
||||||
|
* 增加`run`命令行指令启动内置服务器
|
||||||
|
* `Request`类`pathinfo`方法改进对`cli-server`支持
|
||||||
|
* `Session`类增加`use_lock`配置参数设置是否启用锁机制
|
||||||
|
* 优化`File`缓存自动生成空目录的问题
|
||||||
|
* 域名及分组路由支持`append`方法传递隐式参数
|
||||||
|
* 改进日志的并发写入问题
|
||||||
|
* 改进`Query`类的`where`方法支持传入`Query`对象
|
||||||
|
* 支持设置单个日志文件的文件名
|
||||||
|
* 修正路由规则的域名条件约束
|
||||||
|
* `Request`类增加`subDomain`方法用于获取当前子域名
|
||||||
|
* `Response`类增加`allowCache`方法控制是否允许请求缓存
|
||||||
|
* `Request`类增加`sendData`方法便于扩展
|
||||||
|
* 改进`Env`类不依赖`putenv`方法
|
||||||
|
* 改进控制台`trace`显示错误
|
||||||
|
* 改进`MorphTo`关联
|
||||||
|
* 改进完整路由匹配后带斜线访问出错的情况
|
||||||
|
* 改进路由的多级分组问题
|
||||||
|
* 路由url地址生成支持多级分组
|
||||||
|
* 改进路由Url生成的`url_convert`参数的影响
|
||||||
|
* 改进`miss`和`auto`路由内部解析
|
||||||
|
* 取消预载入关联查询缓存功能
|
||||||
|
|
||||||
|
## V5.1.4 (2018-1-19)
|
||||||
|
|
||||||
|
该版本主要增强了数据库和模型操作,主要更新如下:
|
||||||
|
|
||||||
|
* 支持设置 `deleteTime`属性为`false` 关闭软删除
|
||||||
|
* 模型增加`getError`方法
|
||||||
|
* 改进Query类的`getTableFields`/`getFieldsType`方法 支持表名自动获取
|
||||||
|
* 模型类`toCollection`方法增加参数指定数据集类
|
||||||
|
* 改进`union`查询
|
||||||
|
* 关联预载入`with`方法增加缓存参数
|
||||||
|
* 改进模型类的`get`和`all`方法的缓存 支持关联缓存
|
||||||
|
* 支持`order by field`操作
|
||||||
|
* 改进`insertAll`分批写入
|
||||||
|
* 改进`json`字段数据支持
|
||||||
|
* 增加JSON数据的模型对象化操作
|
||||||
|
* 改进路由`ext`参数检测
|
||||||
|
* 修正`rule`方法的`method`参数使用 `get|post` 方式注册路由的问题
|
||||||
|
|
||||||
|
## V5.1.3 (2018-1-12)
|
||||||
|
|
||||||
|
该版本主要改进了路由及调整函数加载顺序,主要更新如下:
|
||||||
|
|
||||||
|
* 增加`env`助手函数;
|
||||||
|
* 增加`route`助手函数;
|
||||||
|
* 增加视图路由方法;
|
||||||
|
* 增加路由重定向方法;
|
||||||
|
* 路由默认区分最后的目录斜杆(支持设置不区分);
|
||||||
|
* 调整公共文件和配置文件的加载顺序(可以在配置文件中直接使用助手函数);
|
||||||
|
* 视图类增加`filter`方法设置输出过滤;
|
||||||
|
* `view`助手函数增加`filter`参数;
|
||||||
|
* 改进缓存生成指令;
|
||||||
|
* Session类的`get`方法支持获取多级;
|
||||||
|
* Request类`only`方法支持指定默认值;
|
||||||
|
* 改进路由分组;
|
||||||
|
* 修正使用闭包查询的时候自动数据缓存出错的情况;
|
||||||
|
* 废除`view_filter`钩子位置;
|
||||||
|
* 修正分组下面的资源路由;
|
||||||
|
* 改进session驱动;
|
||||||
|
|
||||||
|
## V5.1.2 (2018-1-8)
|
||||||
|
|
||||||
|
该版本改进了配置类及数据库类,主要更新如下:
|
||||||
|
|
||||||
|
* 修正嵌套路由分组;
|
||||||
|
* 修正自定义模板标签界定符后表达式语法出错的情况;
|
||||||
|
* 修正自关联的多次调用问题;
|
||||||
|
* 修正数组查询的`null`条件查询;
|
||||||
|
* 修正Query类的`order`及`field`的一处可能的BUG;
|
||||||
|
* 配置参数设置支持三级;
|
||||||
|
* 配置对象支持`ArrayAccess`;
|
||||||
|
* App类增加`path`方法用于设置应用目录;
|
||||||
|
* 关联定义增加`selfRelation`方法用于设置是否为自关联;
|
||||||
|
|
||||||
|
## V5.1.1 (2018-1-3)
|
||||||
|
|
||||||
|
修正一些反馈的BUG,包括:
|
||||||
|
|
||||||
|
* 修正Cookie类存取数组的问题
|
||||||
|
* 修正Controller的`fetch`方法
|
||||||
|
* 改进跨域请求
|
||||||
|
* 修正`insertAll`方法
|
||||||
|
* 修正`chunk`方法
|
||||||
|
|
||||||
|
## V5.1.0 (2018-1-1)
|
||||||
|
|
||||||
|
主要更新如下:
|
||||||
|
|
||||||
|
* 增加注解路由支持
|
||||||
|
* 路由支持跨域请求设置
|
||||||
|
* 增加`app_dispatch`钩子位置
|
||||||
|
* 修正多对多关联的`detach`方法
|
||||||
|
* 修正软删除的`destroy`方法
|
||||||
|
* Cookie类`httponly`参数默认为false
|
||||||
|
* 日志File驱动增加`single`参数配置记录同一个文件(不按日期生成)
|
||||||
|
* 路由的`ext`和`denyExt`方法支持不传任何参数
|
||||||
|
* 改进模型的`save`方法对`oracle`的支持
|
||||||
|
* Query类的`insertall`方法支持配合`data`和`limit`方法
|
||||||
|
* 增加`whereOr`动态查询支持
|
||||||
|
* 日志的ip地址记录改进
|
||||||
|
* 模型`saveAll`方法支持`isUpdate`方法
|
||||||
|
* 改进`Pivot`模型的实例化操作
|
||||||
|
* 改进Model类的`data`方法
|
||||||
|
* 改进多对多中间表模型类
|
||||||
|
* 模型增加`force`方法强制更新所有数据
|
||||||
|
* Hook类支持设置入口方法名称
|
||||||
|
* 改进验证类
|
||||||
|
* 改进`hasWhere`查询的数据重复问题
|
||||||
|
* 模型的`saveall`方法返回数据集对象
|
||||||
|
* 改进File缓存的`clear`方法
|
||||||
|
* 缓存添加统一的序列化机制
|
||||||
|
* 改进泛三级域名的绑定
|
||||||
|
* 改进泛域名的传值和取值
|
||||||
|
* Request类增加`panDomain`方法
|
||||||
|
* 改进废弃字段判断
|
||||||
|
* App类增加`create`方法用于实例化应用类库
|
||||||
|
* 容器类增加`has`方法
|
||||||
|
* 改进多数据库切换连接
|
||||||
|
* 改进断线重连的异常捕获
|
||||||
|
* 改进模型类`buildQuery`方法
|
||||||
|
* Query类增加`unionAll`方法
|
||||||
|
* 关联统计功能增强(支持Sum/Max/Min/Avg)
|
||||||
|
* 修正延迟写入
|
||||||
|
* chunk方法支持复合主键
|
||||||
|
* 改进JSON类型的写入
|
||||||
|
* 改进Mysql的insertAll方法
|
||||||
|
* Model类`save`方法改进复合主键包含自增的情况
|
||||||
|
* 改进Query类`inc`和`dec`方法的关键字处理
|
||||||
|
* File缓存inc和dec方法保持原来的有效期
|
||||||
|
* 改进redis缓存的有效期判断
|
||||||
|
* 增加checkRule方法用于单独数据的多个验证规则
|
||||||
|
* 修正setDec方法的延迟写入
|
||||||
|
* max和min方法增加force参数
|
||||||
|
* 二级配置参数区分大小写
|
||||||
|
* 改进join方法自关联的问题
|
||||||
|
* 修正关联模型自定义表名的情况
|
||||||
|
* Query类增加getFieldsType和getTableFields方法
|
||||||
|
* 取消视图替换功能及view_replace_str配置参数
|
||||||
|
* 改进域名绑定模块后的额外路由规则问题
|
||||||
|
* 改进mysql的insertAll方法
|
||||||
|
* 改进insertAll方法写入json字段数据的支持
|
||||||
|
* 改进redis长连接多编号库的情况
|
||||||
|
|
||||||
|
## RC3版本(2017-11-6)
|
||||||
|
|
||||||
|
主要更新如下:
|
||||||
|
|
||||||
|
* 改进redis驱动的`get`方法
|
||||||
|
* 修正Query类的`alias`方法
|
||||||
|
* `File`类错误信息支持多语言
|
||||||
|
* 修正路由的额外参数解析
|
||||||
|
* 改进`whereTime`方法
|
||||||
|
* 改进Model类`getAttr`方法
|
||||||
|
* 改进App类的`controller`和`validate`方法支持多层
|
||||||
|
* 改进`HasManyThrough`类
|
||||||
|
* 修正软删除的`restore`方法
|
||||||
|
* 改进`MorpthTo`关联
|
||||||
|
* 改进数据库驱动类的`parseKey`方法
|
||||||
|
* 增加`whereField`动态查询方法
|
||||||
|
* 模型增加废弃字段功能
|
||||||
|
* 改进路由的`after`行为检查和`before`行为机制
|
||||||
|
* 改进路由分组的检查
|
||||||
|
* 修正mysql的`json`字段查询
|
||||||
|
* 取消Connection类的`quote`方法
|
||||||
|
* 改进命令行的支持
|
||||||
|
* 验证信息支持多语言
|
||||||
|
* 修正路由模型绑定
|
||||||
|
* 改进参数绑定类型对枚举类型的支持
|
||||||
|
* 修正模板的`{$Think.version} `输出
|
||||||
|
* 改进模板`date`函数解析
|
||||||
|
* 改进`insertAll`方法支持分批执行
|
||||||
|
* Request类`host`方法支持反向代理
|
||||||
|
* 改进`JumpResponse`支持区分成功和错误模板
|
||||||
|
* 改进开启类库后缀后的关联外键自动识别问题
|
||||||
|
* 修正一对一关联的JOIN方式预载入查询问题
|
||||||
|
* Query类增加`hidden`方法
|
||||||
|
|
||||||
|
## RC2版本(2017-10-17)
|
||||||
|
|
||||||
|
主要更新如下:
|
||||||
|
|
||||||
|
* 修正视图查询
|
||||||
|
* 修正资源路由
|
||||||
|
* 修正`HasMany`关联 修正`where`方法的闭包查询
|
||||||
|
* 一对一关联绑定属性到父模型后 关联属性不再保留
|
||||||
|
* 修正应用的命令行配置文件读取
|
||||||
|
* 改进`Connection`类的`getCacheKey`方法
|
||||||
|
* 改进文件上传的非法图像异常
|
||||||
|
* 改进验证类的`unique`规则
|
||||||
|
* Config类`get`方法支持获取一级配置
|
||||||
|
* 修正count方法对`fetchSql`的支持
|
||||||
|
* 修正mysql驱动对`socket`支持
|
||||||
|
* 改进Connection类的`getRealSql`方法
|
||||||
|
* 修正`view`助手函数
|
||||||
|
* Query类增加`leftJoin` `rightJoin` 和 `fullJoin`方法
|
||||||
|
* 改进app_namespace的获取
|
||||||
|
* 改进`append`方法对一对一`bind`属性的支持
|
||||||
|
* 改进关联的`saveall`方法的返回值
|
||||||
|
* 路由标识设置异常修复
|
||||||
|
* 改进Route类`rule`方法
|
||||||
|
* 改进模型的`table`属性设置
|
||||||
|
* 改进composer autofile的加载顺序
|
||||||
|
* 改进`exception_handle`配置对闭包的支持
|
||||||
|
* 改进app助手函数增加参数
|
||||||
|
* 改进composer的加载路径判断
|
||||||
|
* 修正路由组合变量的URL生成
|
||||||
|
* 修正路由URL生成
|
||||||
|
* 改进`whereTime`查询并支持扩展规则
|
||||||
|
* File类的`move`方法第二个参数支持`false`
|
||||||
|
* 改进Config类
|
||||||
|
* 改进缓存类`remember`方法
|
||||||
|
* 惯例配置文件调整 Url类当普通模式参数的时候不做`urlencode`处理
|
||||||
|
* 取消`ROOT_PATH`和`APP_PATH`常量定义 如需更改应用目录 自己重新定义入口文件
|
||||||
|
* 增加`app_debug`的`Env`获取
|
||||||
|
* 修正泛域名绑定
|
||||||
|
* 改进查询表达式的解析机制
|
||||||
|
* mysql增加`regexp`查询表达式 支持正则查询
|
||||||
|
* 改进查询表达式的异常判断
|
||||||
|
* 改进model类的`destroy`方法
|
||||||
|
* 改进Builder类 取消`parseValue`方法
|
||||||
|
* 修正like查询的参数绑定问题
|
||||||
|
* console和start文件移出核心纳入应用库
|
||||||
|
* 改进Db类主键删除方法
|
||||||
|
* 改进泛域名绑定模块
|
||||||
|
* 取消`BIND_MODULE`常量 改为在入口文件使用`bind`方法设置
|
||||||
|
* 改进数组查询
|
||||||
|
* 改进模板渲染的异常处理
|
||||||
|
* 改进控制器基类的架构方法参数
|
||||||
|
* 改进Controller类的`success`和`error`方法
|
||||||
|
* 改进对浏览器`JSON-Handle`插件的支持
|
||||||
|
* 优化跳转模板的移动端显示
|
||||||
|
* 修正模型查询的`chunk`方法对时间字段的支持
|
||||||
|
* 改进trace驱动
|
||||||
|
* Collection类增加`push`方法
|
||||||
|
* 改进Redis Session驱动
|
||||||
|
* 增加JumpResponse驱动
|
||||||
|
|
||||||
|
|
||||||
|
## RC1(2017-9-8)
|
||||||
|
|
||||||
|
主要新特性为:
|
||||||
|
|
||||||
|
* 引入容器和Facade支持
|
||||||
|
* 依赖注入完善和支持更多场景
|
||||||
|
* 重构的(对象化)路由
|
||||||
|
* 配置和路由目录独立
|
||||||
|
* 取消系统常量
|
||||||
|
* 助手函数增强
|
||||||
|
* 类库别名机制
|
||||||
|
* 模型和数据库增强
|
||||||
|
* 验证类增强
|
||||||
|
* 模板引擎改进
|
||||||
|
* 支持PSR-3日志规范
|
||||||
|
* RC1版本取消了5.0多个字段批量数组查询的方式
|
32
README.md
Normal file
32
README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
DolphinPHP
|
||||||
|
===============
|
||||||
|
|
||||||
|
DophinPHP(海豚PHP)是一个基于ThinkPHP5.1.34 LTS开发的一套开源PHP快速开发框架,DophinPHP秉承极简、极速、极致的开发理念,为开发集成了基于数据-角色的权限管理机制,集成多种灵活快速构建工具,可方便快速扩展的模块、插件、钩子、数据包。统一了模块、插件、钩子、数据包之间的版本和依赖关系,进一步降低了代码和数据的沉余,以方便开发者快速构建自己的应用。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
### 万事俱备-ZBuilder构建神器
|
||||||
|
使用DophinPHP(海豚PHP)自主开发的ZBuilder类,您可以轻松的应对复杂多变的表单、数据列表。数据列表集成类似EXCEL的快速筛选、排序、模糊搜索、AJAX编辑等功能,表单页集成常用的文本、下拉框、单选、多选、关键词、编辑器、文件上传、图片上传、图片裁切等控件,除此之外,您还可以灵活的扩展自己的控件,以便在自己的项目中重复使用。ZBuilder让您更加专注业务逻辑。
|
||||||
|
|
||||||
|
### 相得益彰-模块化组合
|
||||||
|
千变万化的事物之间总是有着千丝万缕的关系,在应用开发的时候,不同的功能、模块甚至数据之间也存在各种依赖关系。在保证模块、插件独立的同时,为了降低代码、数据的沉余,我们将每个模块、插件、数据包加上了唯一的标示和版本号以及彼此之间的依赖关系,保证了应用程序的高内聚低耦合。
|
||||||
|
|
||||||
|
### 一举多得-夸平台支持
|
||||||
|
DophinPHP(海豚PHP)集成BootStrap、JQuery、Xeditable、Select2等优秀的前端开源框架,基于ThinkPHP5出色的性能和REST支持、远程调试和更好的支持API开发。让您可以一次开发即可直接兼容PC、移动设备和微信界面,通过简单的配置即可快速构建属于自己的Android、IOS的APP。
|
||||||
|
|
||||||
|
## 鸣谢
|
||||||
|
感谢[ThinkPHP](http://www.thinkphp.cn)、[JQuery](http://jquery.com/)、[Bootstrap](http://getbootstrap.com/)、[Xeditable](http://vitalets.github.io/x-editable)、[Select2](https://github.com/select2/select2)等优秀开源项目。
|
||||||
|
|
||||||
|
## 官方网站
|
||||||
|
[www.dolphinphp.com](http://www.dolphinphp.com)
|
||||||
|
|
||||||
|
## 版权信息
|
||||||
|
|
||||||
|
DolphinPHP提供个人非商业用途免费使用,商业需授权。
|
||||||
|
|
||||||
|
本项目包含的第三方源码和二进制文件之版权信息另行标注。
|
||||||
|
|
||||||
|
版权所有Copyright © 2016-2019 广东卓锐软件有限公司 (http://www.zrthink.com)
|
||||||
|
|
||||||
|
All rights reserved。
|
||||||
|
|
||||||
|
更多细节参阅 [LICENSE.txt](LICENSE.txt)
|
1
application/.htaccess
Normal file
1
application/.htaccess
Normal file
@ -0,0 +1 @@
|
|||||||
|
deny from all
|
65
application/admin/controller/Action.php
Normal file
65
application/admin/controller/Action.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Action as ActionModel;
|
||||||
|
use app\admin\model\Module as ModuleModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行为管理控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Action extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 首页
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 数据列表
|
||||||
|
$data_list = ActionModel::where($map)->order('id desc')->paginate();
|
||||||
|
// 所有模块的名称和标题
|
||||||
|
$list_module = ModuleModel::getModule();
|
||||||
|
|
||||||
|
// 新增或编辑页面的字段
|
||||||
|
$fields = [
|
||||||
|
['hidden', 'id'],
|
||||||
|
['select', 'module', '所属模块', '', $list_module],
|
||||||
|
['text', 'name', '行为标识', '由英文字母和下划线组成'],
|
||||||
|
['text', 'title', '行为名称', ''],
|
||||||
|
['textarea', 'remark', '行为描述'],
|
||||||
|
['textarea', 'rule', '行为规则', '不写则只记录日志'],
|
||||||
|
['textarea', 'log', '日志规则', '记录日志备注时按此规则来生成,支持[变量|函数]。目前变量有:user,time,model,record,data,details'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setPageTitle('行为管理') // 设置页面标题
|
||||||
|
->setSearch(['name' => '标识', 'title' => '名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['name', '标识'],
|
||||||
|
['title', '名称'],
|
||||||
|
['remark', '描述'],
|
||||||
|
['module', '所属模块', 'callback', function($module, $list_module){
|
||||||
|
return isset($list_module[$module]) ? $list_module[$module] : '未知';
|
||||||
|
}, $list_module],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->autoAdd($fields, '', true, true) // 添加自动新增按钮
|
||||||
|
->autoEdit($fields, '', true, true) // 添加自动编辑按钮
|
||||||
|
->addTopButtons('enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons('delete') // 批量添加右侧按钮
|
||||||
|
->addFilter('module', $list_module)
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
}
|
499
application/admin/controller/Admin.php
Normal file
499
application/admin/controller/Admin.php
Normal file
@ -0,0 +1,499 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\controller\Common;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Menu as MenuModel;
|
||||||
|
use app\admin\model\Module as ModuleModel;
|
||||||
|
use app\admin\model\Icon as IconModel;
|
||||||
|
use app\user\model\Role as RoleModel;
|
||||||
|
use app\user\model\Message as MessageModel;
|
||||||
|
use think\facade\Cache;
|
||||||
|
use think\Db;
|
||||||
|
use think\facade\App;
|
||||||
|
use think\helper\Hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台公共控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Admin extends Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
protected function initialize()
|
||||||
|
{
|
||||||
|
parent::initialize();
|
||||||
|
// 是否拒绝ie浏览器访问
|
||||||
|
if (config('system.deny_ie') && get_browser_type() == 'ie') {
|
||||||
|
$this->redirect('admin/ie/index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否登录,并定义用户ID常量
|
||||||
|
defined('UID') or define('UID', $this->isLogin());
|
||||||
|
|
||||||
|
// 设置当前角色菜单节点权限
|
||||||
|
role_auth();
|
||||||
|
|
||||||
|
// 检查权限
|
||||||
|
if (!RoleModel::checkAuth()) $this->error('权限不足!');
|
||||||
|
|
||||||
|
// 设置分页参数
|
||||||
|
$this->setPageParam();
|
||||||
|
|
||||||
|
// 如果不是ajax请求,则读取菜单
|
||||||
|
if (!$this->request->isAjax()) {
|
||||||
|
// 读取顶部菜单
|
||||||
|
$this->assign('_top_menus', MenuModel::getTopMenu(config('top_menu_max'), '_top_menus'));
|
||||||
|
// 读取全部顶级菜单
|
||||||
|
$this->assign('_top_menus_all', MenuModel::getTopMenu('', '_top_menus_all'));
|
||||||
|
// 获取侧边栏菜单
|
||||||
|
$this->assign('_sidebar_menus', MenuModel::getSidebarMenu());
|
||||||
|
// 获取面包屑导航
|
||||||
|
$this->assign('_location', MenuModel::getLocation('', true));
|
||||||
|
// 获取当前用户未读消息数量
|
||||||
|
$this->assign('_message', MessageModel::getMessageCount());
|
||||||
|
// 获取自定义图标
|
||||||
|
$this->assign('_icons', IconModel::getUrls());
|
||||||
|
// 构建侧栏
|
||||||
|
$data = [
|
||||||
|
'table' => 'admin_config', // 表名或模型名
|
||||||
|
'prefix' => 1,
|
||||||
|
'module' => 'admin',
|
||||||
|
'controller' => 'system',
|
||||||
|
'action' => 'quickedit',
|
||||||
|
];
|
||||||
|
$table_token = substr(sha1('_aside'), 0, 8);
|
||||||
|
session($table_token, $data);
|
||||||
|
$settings = [
|
||||||
|
[
|
||||||
|
'title' => '站点开关',
|
||||||
|
'tips' => '站点关闭后将不能访问',
|
||||||
|
'checked' => Db::name('admin_config')->where('id', 1)->value('value'),
|
||||||
|
'table' => $table_token,
|
||||||
|
'id' => 1,
|
||||||
|
'field' => 'value'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
ZBuilder::make('aside')
|
||||||
|
->addBlock('switch', '系统设置', $settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前操作模型
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return object|\think\db\Query
|
||||||
|
*/
|
||||||
|
final protected function getCurrModel()
|
||||||
|
{
|
||||||
|
$table_token = input('param._t', '');
|
||||||
|
$module = $this->request->module();
|
||||||
|
$controller = parse_name($this->request->controller());
|
||||||
|
|
||||||
|
$table_token == '' && $this->error('缺少参数');
|
||||||
|
!session('?'.$table_token) && $this->error('参数错误');
|
||||||
|
|
||||||
|
$table_data = session($table_token);
|
||||||
|
$table = $table_data['table'];
|
||||||
|
|
||||||
|
$Model = null;
|
||||||
|
if ($table_data['prefix'] == 2) {
|
||||||
|
// 使用模型
|
||||||
|
try {
|
||||||
|
$Model = App::model($table);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->error('找不到模型:'.$table);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 使用DB类
|
||||||
|
$table == '' && $this->error('缺少表名');
|
||||||
|
if ($table_data['module'] != $module || $table_data['controller'] != $controller) {
|
||||||
|
$this->error('非法操作');
|
||||||
|
}
|
||||||
|
|
||||||
|
$Model = $table_data['prefix'] == 0 ? Db::table($table) : Db::name($table);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $Model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置分页参数
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
final protected function setPageParam()
|
||||||
|
{
|
||||||
|
_system_check();
|
||||||
|
$list_rows = input('?param.list_rows') ? input('param.list_rows') : config('list_rows');
|
||||||
|
config('paginate.list_rows', $list_rows);
|
||||||
|
config('paginate.query', input('get.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否登录,没有登录则跳转到登录页面
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
final protected function isLogin()
|
||||||
|
{
|
||||||
|
// 判断是否登录
|
||||||
|
if ($uid = is_signin()) {
|
||||||
|
// 已登录
|
||||||
|
return $uid;
|
||||||
|
} else {
|
||||||
|
// 未登录
|
||||||
|
$this->redirect('user/publics/signin');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable', $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable', $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('delete', $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$type = input('post.type', '');
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$validate = input('post.validate', '');
|
||||||
|
$validate_fields = input('post.validate_fields', '');
|
||||||
|
|
||||||
|
$field == '' && $this->error('缺少字段名');
|
||||||
|
$id == '' && $this->error('缺少主键值');
|
||||||
|
|
||||||
|
$Model = $this->getCurrModel();
|
||||||
|
$protect_table = [
|
||||||
|
'__ADMIN_USER__',
|
||||||
|
'__ADMIN_ROLE__',
|
||||||
|
config('database.prefix').'admin_user',
|
||||||
|
config('database.prefix').'admin_role',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 验证是否操作管理员
|
||||||
|
if (in_array($Model->getTable(), $protect_table) && $id == 1) {
|
||||||
|
$this->error('禁止操作超级管理员');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证器
|
||||||
|
if ($validate != '') {
|
||||||
|
$validate_fields = array_flip(explode(',', $validate_fields));
|
||||||
|
if (isset($validate_fields[$field])) {
|
||||||
|
$result = $this->validate([$field => $value], $validate.'.'.$field);
|
||||||
|
if (true !== $result) $this->error($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
// 日期时间需要转为时间戳
|
||||||
|
case 'combodate':
|
||||||
|
$value = strtotime($value);
|
||||||
|
break;
|
||||||
|
// 开关
|
||||||
|
case 'switch':
|
||||||
|
$value = $value == 'true' ? 1 : 0;
|
||||||
|
break;
|
||||||
|
// 开关
|
||||||
|
case 'password':
|
||||||
|
$value = Hash::make((string)$value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主键名
|
||||||
|
$pk = $Model->getPk();
|
||||||
|
$result = $Model->where($pk, $id)->setField($field, $value);
|
||||||
|
|
||||||
|
cache('hook_plugins', null);
|
||||||
|
cache('system_config', null);
|
||||||
|
cache('access_menus', null);
|
||||||
|
if (false !== $result) {
|
||||||
|
// 记录行为日志
|
||||||
|
if (!empty($record)) {
|
||||||
|
call_user_func_array('action_log', $record);
|
||||||
|
}
|
||||||
|
$this->success('操作成功');
|
||||||
|
} else {
|
||||||
|
$this->error('操作失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动创建添加页面
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 获取表单项
|
||||||
|
$cache_name = $this->request->module().'/'.parse_name($this->request->controller()).'/add';
|
||||||
|
$cache_name = strtolower($cache_name);
|
||||||
|
$form = Cache::get($cache_name, []);
|
||||||
|
if (!$form) {
|
||||||
|
$this->error('自动新增数据不存在,请重新打开此页面');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
$_pop = $this->request->get('_pop');
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
if ($form['validate'] != '') {
|
||||||
|
$result = $this->validate($data, $form['validate']);
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否需要自动插入时间
|
||||||
|
if ($form['auto_time'] != '') {
|
||||||
|
$now_time = $this->request->time();
|
||||||
|
foreach ($form['auto_time'] as $item) {
|
||||||
|
if (strpos($item, '|')) {
|
||||||
|
list($item, $format) = explode('|', $item);
|
||||||
|
$data[$item] = date($format, $now_time);
|
||||||
|
} else {
|
||||||
|
$data[$item] = $form['format'] != '' ? date($form['format'], $now_time) : $now_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入数据
|
||||||
|
if (Db::name($form['table'])->insert($data)) {
|
||||||
|
if ($_pop == 1) {
|
||||||
|
$this->success('新增成功', null, '_parent_reload');
|
||||||
|
} else {
|
||||||
|
$this->success('新增成功', $form['go_back']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems($form['items'])
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动创建编辑页面
|
||||||
|
* @param string $id 主键值
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function edit($id = '')
|
||||||
|
{
|
||||||
|
if ($id === '') $this->error('参数错误');
|
||||||
|
|
||||||
|
// 获取表单项
|
||||||
|
$cache_name = $this->request->module().'/'.parse_name($this->request->controller()).'/edit';
|
||||||
|
$cache_name = strtolower($cache_name);
|
||||||
|
$form = Cache::get($cache_name, []);
|
||||||
|
if (!$form) {
|
||||||
|
$this->error('自动编辑数据不存在,请重新打开此页面');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
$_pop = $this->request->get('_pop');
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
if ($form['validate'] != '') {
|
||||||
|
$result = $this->validate($data, $form['validate']);
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否需要自动插入时间
|
||||||
|
if ($form['auto_time'] != '') {
|
||||||
|
$now_time = $this->request->time();
|
||||||
|
foreach ($form['auto_time'] as $item) {
|
||||||
|
if (strpos($item, '|')) {
|
||||||
|
list($item, $format) = explode('|', $item);
|
||||||
|
$data[$item] = date($format, $now_time);
|
||||||
|
} else {
|
||||||
|
$data[$item] = $form['format'] != '' ? date($form['format'], $now_time) : $now_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新数据
|
||||||
|
if (false !== Db::name($form['table'])->update($data)) {
|
||||||
|
if ($_pop == 1) {
|
||||||
|
$this->success('编辑成功', null, '_parent_reload');
|
||||||
|
} else {
|
||||||
|
$this->success('编辑成功', $form['go_back']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$info = Db::name($form['table'])->find($id);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('编辑')
|
||||||
|
->addFormItems($form['items'])
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置状态
|
||||||
|
* 禁用、启用、删除都是调用这个内部方法
|
||||||
|
* @param string $type 操作类型:enable,disable,delete
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$ids = (array)$ids;
|
||||||
|
$field = input('param.field', 'status');
|
||||||
|
|
||||||
|
empty($ids) && $this->error('缺少主键');
|
||||||
|
|
||||||
|
$Model = $this->getCurrModel();
|
||||||
|
$protect_table = [
|
||||||
|
'__ADMIN_USER__',
|
||||||
|
'__ADMIN_ROLE__',
|
||||||
|
'__ADMIN_MODULE__',
|
||||||
|
config('database.prefix').'admin_user',
|
||||||
|
config('database.prefix').'admin_role',
|
||||||
|
config('database.prefix').'admin_module',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 禁止操作核心表的主要数据
|
||||||
|
if (in_array($Model->getTable(), $protect_table) && in_array('1', $ids)) {
|
||||||
|
$this->error('禁止操作');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主键名称
|
||||||
|
$pk = $Model->getPk();
|
||||||
|
$map = [
|
||||||
|
[$pk, 'in', $ids]
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = false;
|
||||||
|
switch ($type) {
|
||||||
|
case 'disable': // 禁用
|
||||||
|
$result = $Model->where($map)->setField($field, 0);
|
||||||
|
break;
|
||||||
|
case 'enable': // 启用
|
||||||
|
$result = $Model->where($map)->setField($field, 1);
|
||||||
|
break;
|
||||||
|
case 'delete': // 删除
|
||||||
|
$result = $Model->where($map)->delete();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->error('非法操作');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false !== $result) {
|
||||||
|
Cache::clear();
|
||||||
|
// 记录行为日志
|
||||||
|
if (!empty($record)) {
|
||||||
|
call_user_func_array('action_log', $record);
|
||||||
|
}
|
||||||
|
$this->success('操作成功');
|
||||||
|
} else {
|
||||||
|
$this->error('操作失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模块设置
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function moduleConfig()
|
||||||
|
{
|
||||||
|
// 当前模块名
|
||||||
|
$module = $this->request->module();
|
||||||
|
|
||||||
|
// 保存
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
$data = json_encode($data);
|
||||||
|
|
||||||
|
if (false !== ModuleModel::where('name', $module)->update(['config' => $data])) {
|
||||||
|
cache('module_config_'.$module, null);
|
||||||
|
$this->success('更新成功');
|
||||||
|
} else {
|
||||||
|
$this->error('更新失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模块配置信息
|
||||||
|
$module_info = ModuleModel::getInfoFromFile($module);
|
||||||
|
$config = $module_info['config'];
|
||||||
|
$trigger = isset($module_info['trigger']) ? $module_info['trigger'] : [];
|
||||||
|
|
||||||
|
// 数据库内的模块信息
|
||||||
|
$db_config = ModuleModel::where('name', $module)->value('config');
|
||||||
|
$db_config = json_decode($db_config, true);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('模块设置')
|
||||||
|
->addFormItems($config)
|
||||||
|
->setFormdata($db_config) // 设置表格数据
|
||||||
|
->setTrigger($trigger) // 设置触发
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
}
|
235
application/admin/controller/Ajax.php
Normal file
235
application/admin/controller/Ajax.php
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\controller\Common;
|
||||||
|
use app\admin\model\Menu as MenuModel;
|
||||||
|
use app\admin\model\Attachment as AttachmentModel;
|
||||||
|
use think\facade\Cache;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于处理ajax请求的控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Ajax extends Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取联动数据
|
||||||
|
* @param string $token token
|
||||||
|
* @param int $pid 父级ID
|
||||||
|
* @param string $pidkey 父级id字段名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function getLevelData($token = '', $pid = 0, $pidkey = 'pid')
|
||||||
|
{
|
||||||
|
if ($token == '') {
|
||||||
|
return json(['code' => 0, 'msg' => '缺少Token']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$token_data = session($token);
|
||||||
|
$table = $token_data['table'];
|
||||||
|
$option = $token_data['option'];
|
||||||
|
$key = $token_data['key'];
|
||||||
|
|
||||||
|
$data_list = Db::name($table)->where($pidkey, $pid)->column($option, $key);
|
||||||
|
|
||||||
|
if ($data_list === false) {
|
||||||
|
return json(['code' => 0, 'msg' => '查询失败']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data_list) {
|
||||||
|
$result = [
|
||||||
|
'code' => 1,
|
||||||
|
'msg' => '请求成功',
|
||||||
|
'list' => format_linkage($data_list)
|
||||||
|
];
|
||||||
|
return json($result);
|
||||||
|
} else {
|
||||||
|
return json(['code' => 0, 'msg' => '查询不到数据']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取筛选数据
|
||||||
|
* @param string $token
|
||||||
|
* @param array $map 查询条件
|
||||||
|
* @param string $options 选项,用于显示转换
|
||||||
|
* @param string $list 选项缓存列表名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function getFilterList($token = '', $map = [], $options = '', $list = '')
|
||||||
|
{
|
||||||
|
if ($list != '') {
|
||||||
|
$result = [
|
||||||
|
'code' => 1,
|
||||||
|
'msg' => '请求成功',
|
||||||
|
'list' => Cache::get($list)
|
||||||
|
];
|
||||||
|
return json($result);
|
||||||
|
}
|
||||||
|
if ($token == '') {
|
||||||
|
return json(['code' => 0, 'msg' => '缺少Token']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$token_data = session($token);
|
||||||
|
$table = $token_data['table'];
|
||||||
|
$field = $token_data['field'];
|
||||||
|
|
||||||
|
if ($field == '') {
|
||||||
|
return json(['code' => 0, 'msg' => '缺少字段']);
|
||||||
|
}
|
||||||
|
if (!empty($map) && is_array($map)) {
|
||||||
|
foreach ($map as &$item) {
|
||||||
|
if (is_array($item)) {
|
||||||
|
foreach ($item as &$value) {
|
||||||
|
$value = trim($value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$item = trim($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strpos($table, '/')) {
|
||||||
|
$data_list = model($table)->where($map)->group($field)->column($field);
|
||||||
|
} else {
|
||||||
|
$data_list = Db::name($table)->where($map)->group($field)->column($field);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data_list === false) {
|
||||||
|
return json(['code' => 0, 'msg' => '查询失败']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data_list) {
|
||||||
|
if ($options != '') {
|
||||||
|
// 从缓存获取选项数据
|
||||||
|
$options = cache($options);
|
||||||
|
if ($options) {
|
||||||
|
$temp_data_list = [];
|
||||||
|
foreach ($data_list as $item) {
|
||||||
|
$temp_data_list[$item] = isset($options[$item]) ? $options[$item] : '';
|
||||||
|
}
|
||||||
|
$data_list = $temp_data_list;
|
||||||
|
} else {
|
||||||
|
$data_list = parse_array($data_list);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$data_list = parse_array($data_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'code' => 1,
|
||||||
|
'msg' => '请求成功',
|
||||||
|
'list' => $data_list
|
||||||
|
];
|
||||||
|
return json($result);
|
||||||
|
} else {
|
||||||
|
return json(['code' => 0, 'msg' => '查询不到数据']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定模块的菜单
|
||||||
|
* @param string $module 模块名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getModuleMenus($module = '')
|
||||||
|
{
|
||||||
|
if (!is_signin()) {
|
||||||
|
$this->error('请先登录');
|
||||||
|
}
|
||||||
|
$menus = MenuModel::getMenuTree(0, '', $module);
|
||||||
|
$result = [
|
||||||
|
'code' => 1,
|
||||||
|
'msg' => '请求成功',
|
||||||
|
'list' => format_linkage($menus)
|
||||||
|
];
|
||||||
|
return json($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置配色方案
|
||||||
|
* @param string $theme 配色名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function setTheme($theme = '') {
|
||||||
|
if (!is_signin()) {
|
||||||
|
$this->error('请先登录');
|
||||||
|
}
|
||||||
|
$themes = ['default', 'amethyst', 'city', 'flat', 'modern', 'smooth'];
|
||||||
|
if (!in_array($theme, $themes)) {
|
||||||
|
$this->error('非法操作');
|
||||||
|
}
|
||||||
|
$map['name'] = 'system_color';
|
||||||
|
$map['group'] = 'system';
|
||||||
|
|
||||||
|
if (Db::name('admin_config')->where($map)->setField('value', $theme)) {
|
||||||
|
$this->success('设置成功');
|
||||||
|
} else {
|
||||||
|
$this->error('设置失败,请重试');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取侧栏菜单
|
||||||
|
* @param string $module_id 模块id
|
||||||
|
* @param string $module 模型名
|
||||||
|
* @param string $controller 控制器名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSidebarMenu($module_id = '', $module = '', $controller = '')
|
||||||
|
{
|
||||||
|
if (!is_signin()) {
|
||||||
|
$this->error('登录已失效,请重新登录', 'user/publics/signin');
|
||||||
|
}
|
||||||
|
|
||||||
|
role_auth();
|
||||||
|
$menus = MenuModel::getSidebarMenu($module_id, $module, $controller);
|
||||||
|
|
||||||
|
$output = '';
|
||||||
|
foreach ($menus as $key => $menu) {
|
||||||
|
if (!empty($menu['url_value'])) {
|
||||||
|
$output = $menu['url_value'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!empty($menu['child'])) {
|
||||||
|
$output = $menu['child'][0]['url_value'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->success('获取成功', null, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查附件是否存在
|
||||||
|
* @param string $md5 文件md5
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function check($md5 = '')
|
||||||
|
{
|
||||||
|
$md5 == '' && $this->error('参数错误');
|
||||||
|
|
||||||
|
// 判断附件是否已存在
|
||||||
|
if ($file_exists = AttachmentModel::get(['md5' => $md5])) {
|
||||||
|
if ($file_exists['driver'] == 'local') {
|
||||||
|
$file_path = PUBLIC_PATH.$file_exists['path'];
|
||||||
|
} else {
|
||||||
|
$file_path = $file_exists['path'];
|
||||||
|
}
|
||||||
|
return json([
|
||||||
|
'code' => 1,
|
||||||
|
'info' => '上传成功',
|
||||||
|
'class' => 'success',
|
||||||
|
'id' => $file_exists['id'],
|
||||||
|
'path' => $file_path
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$this->error('文件不存在');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
796
application/admin/controller/Attachment.php
Normal file
796
application/admin/controller/Attachment.php
Normal file
@ -0,0 +1,796 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Attachment as AttachmentModel;
|
||||||
|
use think\Image;
|
||||||
|
use think\File;
|
||||||
|
use think\facade\Hook;
|
||||||
|
use think\Db;
|
||||||
|
use think\facade\Env;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附件控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Attachment extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 附件列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
|
||||||
|
// 数据列表
|
||||||
|
$data_list = AttachmentModel::where($map)->order('sort asc,id desc')->paginate();
|
||||||
|
foreach ($data_list as $key => &$value) {
|
||||||
|
if (in_array(strtolower($value['ext']), ['jpg', 'jpeg', 'png', 'gif', 'bmp'])) {
|
||||||
|
if ($value['driver'] == 'local') {
|
||||||
|
$thumb = $value['thumb'] != '' ? $value['thumb'] : $value['path'];
|
||||||
|
$value['type'] = '<div class="js-gallery"><img class="image" title="点击查看大图" data-original="'. PUBLIC_PATH . $value['path'].'" src="'. PUBLIC_PATH . $thumb.'"></div>';
|
||||||
|
} else {
|
||||||
|
$value['type'] = '<div class="js-gallery"><img class="image" title="点击查看大图" data-original="'. $value['path'].'" src="'. $value['path'].'"></div>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($value['driver'] == 'local') {
|
||||||
|
$path = PUBLIC_PATH. $value['path'];
|
||||||
|
} else {
|
||||||
|
$path = $value['path'];
|
||||||
|
}
|
||||||
|
if (is_file('.'.config('public_static_path').'admin/img/files/'.$value['ext'].'.png')) {
|
||||||
|
$value['type'] = '<a href="'. $path.'"
|
||||||
|
data-toggle="tooltip" title="点击下载">
|
||||||
|
<img class="image" src="'.config('public_static_path').'admin/img/files/'.$value['ext'].'.png"></a>';
|
||||||
|
} else {
|
||||||
|
$value['type'] = '<a href="'. $path.'"
|
||||||
|
data-toggle="tooltip" title="点击下载">
|
||||||
|
<img class="image" src="'.config('public_static_path').'admin/img/files/file.png"></a>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['name' => '名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['type', '类型'],
|
||||||
|
['name', '名称'],
|
||||||
|
['size', '大小', 'byte'],
|
||||||
|
['driver', '上传驱动', parse_attr(Db::name('admin_config')->where('name', 'upload_driver')->value('options'))],
|
||||||
|
['create_time', '上传时间', 'datetime'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons('delete') // 批量添加右侧按钮
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传附件
|
||||||
|
* @param string $dir 保存的目录:images,files,videos,voices
|
||||||
|
* @param string $from 来源,wangeditor:wangEditor编辑器, ueditor:ueditor编辑器, editormd:editormd编辑器等
|
||||||
|
* @param string $module 来自哪个模块
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function upload($dir = '', $from = '', $module = '')
|
||||||
|
{
|
||||||
|
// 临时取消执行时间限制
|
||||||
|
set_time_limit(0);
|
||||||
|
if ($dir == '') $this->error('没有指定上传目录');
|
||||||
|
if ($from == 'ueditor') return $this->ueditor();
|
||||||
|
if ($from == 'jcrop') return $this->jcrop();
|
||||||
|
return $this->saveFile($dir, $from, $module);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存附件
|
||||||
|
* @param string $dir 附件存放的目录
|
||||||
|
* @param string $from 来源
|
||||||
|
* @param string $module 来自哪个模块
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string|\think\response\Json
|
||||||
|
*/
|
||||||
|
private function saveFile($dir = '', $from = '', $module = '')
|
||||||
|
{
|
||||||
|
// 附件大小限制
|
||||||
|
$size_limit = $dir == 'images' ? config('upload_image_size') : config('upload_file_size');
|
||||||
|
$size_limit = $size_limit * 1024;
|
||||||
|
// 附件类型限制
|
||||||
|
$ext_limit = $dir == 'images' ? config('upload_image_ext') : config('upload_file_ext');
|
||||||
|
$ext_limit = $ext_limit != '' ? parse_attr($ext_limit) : '';
|
||||||
|
// 缩略图参数
|
||||||
|
$thumb = $this->request->post('thumb', '');
|
||||||
|
// 水印参数
|
||||||
|
$watermark = $this->request->post('watermark', '');
|
||||||
|
|
||||||
|
// 获取附件数据
|
||||||
|
$callback = '';
|
||||||
|
switch ($from) {
|
||||||
|
case 'editormd':
|
||||||
|
$file_input_name = 'editormd-image-file';
|
||||||
|
break;
|
||||||
|
case 'ckeditor':
|
||||||
|
$file_input_name = 'upload';
|
||||||
|
$callback = $this->request->get('CKEditorFuncNum');
|
||||||
|
break;
|
||||||
|
case 'ueditor_scrawl':
|
||||||
|
return $this->saveScrawl();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$file_input_name = 'file';
|
||||||
|
}
|
||||||
|
$file = $this->request->file($file_input_name);
|
||||||
|
|
||||||
|
// 判断附件是否已存在
|
||||||
|
if ($file_exists = AttachmentModel::get(['md5' => $file->hash('md5')])) {
|
||||||
|
if ($file_exists['driver'] == 'local') {
|
||||||
|
$file_path = PUBLIC_PATH. $file_exists['path'];
|
||||||
|
} else {
|
||||||
|
$file_path = $file_exists['path'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 附件已存在
|
||||||
|
return $this->uploadSuccess($from, $file_path, $file_exists['name'], $file_exists['id'], $callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断附件大小是否超过限制
|
||||||
|
if ($size_limit > 0 && ($file->getInfo('size') > $size_limit)) {
|
||||||
|
return $this->uploadError($from, '附件过大', $callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断附件格式是否符合
|
||||||
|
$file_name = $file->getInfo('name');
|
||||||
|
$file_ext = strtolower(substr($file_name, strrpos($file_name, '.')+1));
|
||||||
|
$error_msg = '';
|
||||||
|
if ($ext_limit == '') {
|
||||||
|
$error_msg = '获取文件信息失败!';
|
||||||
|
}
|
||||||
|
if ($file->getMime() == 'text/x-php' || $file->getMime() == 'text/html') {
|
||||||
|
$error_msg = '禁止上传非法文件!';
|
||||||
|
}
|
||||||
|
if (preg_grep("/php/i", $ext_limit)) {
|
||||||
|
$error_msg = '禁止上传非法文件!';
|
||||||
|
}
|
||||||
|
if (!preg_grep("/$file_ext/i", $ext_limit)) {
|
||||||
|
$error_msg = '附件类型不正确!';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error_msg != '') {
|
||||||
|
// 上传错误
|
||||||
|
return $this->uploadError($from, $error_msg, $callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 附件上传钩子,用于第三方文件上传扩展
|
||||||
|
if (config('upload_driver') != 'local') {
|
||||||
|
$hook_result = Hook::listen('upload_attachment', ['file' => $file, 'from' => $from, 'module' => $module], true);
|
||||||
|
if (false !== $hook_result) {
|
||||||
|
return $hook_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动到框架应用根目录/uploads/ 目录下
|
||||||
|
$info = $file->move(config('upload_path') . DIRECTORY_SEPARATOR . $dir);
|
||||||
|
if($info){
|
||||||
|
// 缩略图路径
|
||||||
|
$thumb_path_name = '';
|
||||||
|
// 图片宽度
|
||||||
|
$img_width = '';
|
||||||
|
// 图片高度
|
||||||
|
$img_height = '';
|
||||||
|
if ($dir == 'images') {
|
||||||
|
$img = Image::open($info);
|
||||||
|
$img_width = $img->width();
|
||||||
|
$img_height = $img->height();
|
||||||
|
// 水印功能
|
||||||
|
if ($watermark == '') {
|
||||||
|
if (config('upload_thumb_water') == 1 && config('upload_thumb_water_pic') > 0) {
|
||||||
|
$this->create_water($info->getRealPath(), config('upload_thumb_water_pic'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strtolower($watermark) != 'close') {
|
||||||
|
list($watermark_img, $watermark_pos, $watermark_alpha) = explode('|', $watermark);
|
||||||
|
$this->create_water($info->getRealPath(), $watermark_img, $watermark_pos, $watermark_alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成缩略图
|
||||||
|
if ($thumb == '') {
|
||||||
|
if (config('upload_image_thumb') != '') {
|
||||||
|
$thumb_path_name = $this->create_thumb($info, $info->getPathInfo()->getfileName(), $info->getFilename());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strtolower($thumb) != 'close') {
|
||||||
|
list($thumb_size, $thumb_type) = explode('|', $thumb);
|
||||||
|
$thumb_path_name = $this->create_thumb($info, $info->getPathInfo()->getfileName(), $info->getFilename(), $thumb_size, $thumb_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取附件信息
|
||||||
|
$file_info = [
|
||||||
|
'uid' => session('user_auth.uid'),
|
||||||
|
'name' => $file->getInfo('name'),
|
||||||
|
'mime' => $file->getInfo('type'),
|
||||||
|
'path' => 'uploads/' . $dir . '/' . str_replace('\\', '/', $info->getSaveName()),
|
||||||
|
'ext' => $info->getExtension(),
|
||||||
|
'size' => $info->getSize(),
|
||||||
|
'md5' => $info->hash('md5'),
|
||||||
|
'sha1' => $info->hash('sha1'),
|
||||||
|
'thumb' => $thumb_path_name,
|
||||||
|
'module' => $module,
|
||||||
|
'width' => $img_width,
|
||||||
|
'height' => $img_height,
|
||||||
|
];
|
||||||
|
|
||||||
|
// 写入数据库
|
||||||
|
if ($file_add = AttachmentModel::create($file_info)) {
|
||||||
|
$file_path = PUBLIC_PATH. $file_info['path'];
|
||||||
|
return $this->uploadSuccess($from, $file_path, $file_info['name'], $file_add['id'], $callback);
|
||||||
|
} else {
|
||||||
|
return $this->uploadError($from, '上传失败', $callback);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return $this->uploadError($from, $file->getError(), $callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理ueditor上传
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string|\think\response\Json
|
||||||
|
*/
|
||||||
|
private function ueditor(){
|
||||||
|
$action = $this->request->get('action');
|
||||||
|
$config_file = './static/libs/ueditor/php/config.json';
|
||||||
|
$config = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents($config_file)), true);
|
||||||
|
switch ($action) {
|
||||||
|
/* 获取配置信息 */
|
||||||
|
case 'config':
|
||||||
|
$result = $config;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 上传图片 */
|
||||||
|
case 'uploadimage':
|
||||||
|
return $this->saveFile('images', 'ueditor');
|
||||||
|
break;
|
||||||
|
/* 上传涂鸦 */
|
||||||
|
case 'uploadscrawl':
|
||||||
|
return $this->saveFile('images', 'ueditor_scrawl');
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 上传视频 */
|
||||||
|
case 'uploadvideo':
|
||||||
|
return $this->saveFile('videos', 'ueditor');
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 上传附件 */
|
||||||
|
case 'uploadfile':
|
||||||
|
return $this->saveFile('files', 'ueditor');
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 列出图片 */
|
||||||
|
case 'listimage':
|
||||||
|
return $this->showFile('listimage', $config);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 列出附件 */
|
||||||
|
case 'listfile':
|
||||||
|
return $this->showFile('listfile', $config);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 抓取远程附件 */
|
||||||
|
// case 'catchimage':
|
||||||
|
// $result = include("action_crawler.php");
|
||||||
|
// break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$result = ['state' => '请求地址出错'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 输出结果 */
|
||||||
|
if (isset($_GET["callback"])) {
|
||||||
|
if (preg_match("/^[\w_]+$/", $_GET["callback"])) {
|
||||||
|
return htmlspecialchars($_GET["callback"]) . '(' . $result . ')';
|
||||||
|
} else {
|
||||||
|
return json(['state' => 'callback参数不合法']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return json($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存涂鸦(ueditor)
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
private function saveScrawl()
|
||||||
|
{
|
||||||
|
$file = $this->request->post('file');
|
||||||
|
$file_content = base64_decode($file);
|
||||||
|
$file_name = md5($file) . '.jpg';
|
||||||
|
$dir = config('upload_path') . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . date('Ymd', $this->request->time());
|
||||||
|
$file_path = $dir . DIRECTORY_SEPARATOR . $file_name;
|
||||||
|
|
||||||
|
if (!is_dir($dir)) {
|
||||||
|
mkdir($dir, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === file_put_contents($file_path, $file_content)) {
|
||||||
|
return json(['state' => '涂鸦上传出错']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = new File($file_path);
|
||||||
|
$img = Image::open($file);
|
||||||
|
$file_info = [
|
||||||
|
'uid' => session('user_auth.uid'),
|
||||||
|
'name' => $file_name,
|
||||||
|
'mime' => 'image/png',
|
||||||
|
'path' => 'uploads/images/' . date('Ymd', $this->request->time()) . '/' . $file_name,
|
||||||
|
'ext' => 'png',
|
||||||
|
'size' => $file->getSize(),
|
||||||
|
'md5' => $file->hash('md5'),
|
||||||
|
'sha1' => $file->hash('sha1'),
|
||||||
|
'module' => $this->request->module(),
|
||||||
|
'width' => $img->width(),
|
||||||
|
'height' => $img->height()
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($file_add = AttachmentModel::create($file_info)) {
|
||||||
|
// 返回成功信息
|
||||||
|
return json([
|
||||||
|
"state" => "SUCCESS", // 上传状态,上传成功时必须返回"SUCCESS"
|
||||||
|
"url" => PUBLIC_PATH. $file_info['path'], // 返回的地址
|
||||||
|
"title" => $file_info['name'], // 附件名
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json(['state' => '涂鸦上传出错']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示附件列表(ueditor)
|
||||||
|
* @param string $type 类型
|
||||||
|
* @param $config
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
private function showFile($type, $config){
|
||||||
|
/* 判断类型 */
|
||||||
|
switch ($type) {
|
||||||
|
/* 列出附件 */
|
||||||
|
case 'listfile':
|
||||||
|
$allowFiles = $config['fileManagerAllowFiles'];
|
||||||
|
$listSize = $config['fileManagerListSize'];
|
||||||
|
$path = realpath(config('upload_path') .'/files/');
|
||||||
|
break;
|
||||||
|
/* 列出图片 */
|
||||||
|
case 'listimage':
|
||||||
|
default:
|
||||||
|
$allowFiles = $config['imageManagerAllowFiles'];
|
||||||
|
$listSize = $config['imageManagerListSize'];
|
||||||
|
$path = realpath(config('upload_path') .'/images/');
|
||||||
|
}
|
||||||
|
$allowFiles = substr(str_replace(".", "|", join("", $allowFiles)), 1);
|
||||||
|
|
||||||
|
/* 获取参数 */
|
||||||
|
$size = isset($_GET['size']) ? htmlspecialchars($_GET['size']) : $listSize;
|
||||||
|
$start = isset($_GET['start']) ? htmlspecialchars($_GET['start']) : 0;
|
||||||
|
$end = $start + $size;
|
||||||
|
|
||||||
|
/* 获取附件列表 */
|
||||||
|
$files = $this->getfiles($path, $allowFiles);
|
||||||
|
if (!count($files)) {
|
||||||
|
return json(array(
|
||||||
|
"state" => "no match file",
|
||||||
|
"list" => array(),
|
||||||
|
"start" => $start,
|
||||||
|
"total" => count($files)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 获取指定范围的列表 */
|
||||||
|
$len = count($files);
|
||||||
|
for ($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--){
|
||||||
|
$list[] = $files[$i];
|
||||||
|
}
|
||||||
|
//倒序
|
||||||
|
//for ($i = $end, $list = array(); $i < $len && $i < $end; $i++){
|
||||||
|
// $list[] = $files[$i];
|
||||||
|
//}
|
||||||
|
|
||||||
|
/* 返回数据 */
|
||||||
|
$result = array(
|
||||||
|
"state" => "SUCCESS",
|
||||||
|
"list" => $list,
|
||||||
|
"start" => $start,
|
||||||
|
"total" => count($files)
|
||||||
|
);
|
||||||
|
|
||||||
|
return json($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理Jcrop图片裁剪
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function jcrop()
|
||||||
|
{
|
||||||
|
$file_path = $this->request->post('path', '');
|
||||||
|
$cut_info = $this->request->post('cut', '');
|
||||||
|
$thumb = $this->request->post('thumb', '');
|
||||||
|
$watermark = $this->request->post('watermark', '');
|
||||||
|
$module = $this->request->param('module', '');
|
||||||
|
|
||||||
|
// 上传图片
|
||||||
|
if ($file_path == '') {
|
||||||
|
$file = $this->request->file('file');
|
||||||
|
|
||||||
|
// 附件类型限制
|
||||||
|
$ext_limit = config('upload_image_ext');
|
||||||
|
$ext_limit = $ext_limit != '' ? parse_attr($ext_limit) : '';
|
||||||
|
|
||||||
|
// 判断附件格式是否符合
|
||||||
|
$file_name = $file->getInfo('name');
|
||||||
|
$file_ext = strtolower(substr($file_name, strrpos($file_name, '.')+1));
|
||||||
|
|
||||||
|
if ($ext_limit == '') {
|
||||||
|
$this->error('获取文件信息失败!');
|
||||||
|
}
|
||||||
|
if (strtolower($file_ext) == 'php') {
|
||||||
|
$this->error('禁止上传非法文件!');
|
||||||
|
}
|
||||||
|
if ($file->getMime() == 'text/x-php' || $file->getMime() == 'text/html') {
|
||||||
|
$this->error('禁止上传非法文件!');
|
||||||
|
}
|
||||||
|
if (preg_grep("/php/i", $ext_limit)) {
|
||||||
|
$this->error('禁止上传非法文件!');
|
||||||
|
}
|
||||||
|
if (!preg_grep("/$file_ext/i", $ext_limit)) {
|
||||||
|
$this->error('附件类型不正确!');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_dir(config('upload_temp_path'))) {
|
||||||
|
mkdir(config('upload_temp_path'), 0766, true);
|
||||||
|
}
|
||||||
|
$info = $file->move(config('upload_temp_path'), $file->hash('md5'));
|
||||||
|
if ($info) {
|
||||||
|
return json(['code' => 1, 'src' => PUBLIC_PATH. 'uploads/temp/'. $info->getFilename()]);
|
||||||
|
} else {
|
||||||
|
$this->error('上传失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file_path = config('upload_temp_path') . str_replace(PUBLIC_PATH. 'uploads/temp/', '', $file_path);
|
||||||
|
|
||||||
|
if (is_file($file_path)) {
|
||||||
|
// 获取裁剪信息
|
||||||
|
$cut_info = explode(',', $cut_info);
|
||||||
|
|
||||||
|
// 读取图片
|
||||||
|
$image = Image::open($file_path);
|
||||||
|
|
||||||
|
$dir_name = date('Ymd');
|
||||||
|
$file_dir = config('upload_path') . DIRECTORY_SEPARATOR . 'images/' . $dir_name . '/';
|
||||||
|
if (!is_dir($file_dir)) {
|
||||||
|
mkdir($file_dir, 0766, true);
|
||||||
|
}
|
||||||
|
$file_name = md5(microtime(true)) . '.' . $image->type();
|
||||||
|
$new_file_path = $file_dir . $file_name;
|
||||||
|
|
||||||
|
// 裁剪图片
|
||||||
|
$image->crop($cut_info[0], $cut_info[1], $cut_info[2], $cut_info[3], $cut_info[4], $cut_info[5])->save($new_file_path);
|
||||||
|
|
||||||
|
// 水印功能
|
||||||
|
if ($watermark == '') {
|
||||||
|
if (config('upload_thumb_water') == 1 && config('upload_thumb_water_pic') > 0) {
|
||||||
|
$this->create_water($new_file_path, config('upload_thumb_water_pic'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strtolower($watermark) != 'close') {
|
||||||
|
list($watermark_img, $watermark_pos, $watermark_alpha) = explode('|', $watermark);
|
||||||
|
$this->create_water($new_file_path, $watermark_img, $watermark_pos, $watermark_alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否创建缩略图
|
||||||
|
$thumb_path_name = '';
|
||||||
|
if ($thumb == '') {
|
||||||
|
if (config('upload_image_thumb') != '') {
|
||||||
|
$thumb_path_name = $this->create_thumb($new_file_path, $dir_name, $file_name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strtolower($thumb) != 'close') {
|
||||||
|
list($thumb_size, $thumb_type) = explode('|', $thumb);
|
||||||
|
$thumb_path_name = $this->create_thumb($new_file_path, $dir_name, $file_name, $thumb_size, $thumb_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存图片
|
||||||
|
$file = new File($new_file_path);
|
||||||
|
$file_info = [
|
||||||
|
'uid' => session('user_auth.uid'),
|
||||||
|
'name' => $file_name,
|
||||||
|
'mime' => $image->mime(),
|
||||||
|
'path' => 'uploads/images/' . $dir_name . '/' . $file_name,
|
||||||
|
'ext' => $image->type(),
|
||||||
|
'size' => $file->getSize(),
|
||||||
|
'md5' => $file->hash('md5'),
|
||||||
|
'sha1' => $file->hash('sha1'),
|
||||||
|
'thumb' => $thumb_path_name,
|
||||||
|
'module' => $module,
|
||||||
|
'width' => $image->width(),
|
||||||
|
'height' => $image->height()
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($file_add = AttachmentModel::create($file_info)) {
|
||||||
|
// 删除临时图片
|
||||||
|
unlink($file_path);
|
||||||
|
// 返回成功信息
|
||||||
|
return json([
|
||||||
|
'code' => 1,
|
||||||
|
'id' => $file_add['id'],
|
||||||
|
'src' => PUBLIC_PATH . $file_info['path'],
|
||||||
|
'thumb' => $thumb_path_name == '' ? '' : PUBLIC_PATH . $thumb_path_name,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$this->error('上传失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->error('文件不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建缩略图
|
||||||
|
* @param string $file 目标文件,可以是文件对象或文件路径
|
||||||
|
* @param string $dir 保存目录,即目标文件所在的目录名
|
||||||
|
* @param string $save_name 缩略图名
|
||||||
|
* @param string $thumb_size 尺寸
|
||||||
|
* @param string $thumb_type 裁剪类型
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string 缩略图路径
|
||||||
|
*/
|
||||||
|
private function create_thumb($file = '', $dir = '', $save_name = '', $thumb_size = '', $thumb_type = '')
|
||||||
|
{
|
||||||
|
// 获取要生成的缩略图最大宽度和高度
|
||||||
|
$thumb_size = $thumb_size == '' ? config('upload_image_thumb') : $thumb_size;
|
||||||
|
list($thumb_max_width, $thumb_max_height) = explode(',', $thumb_size);
|
||||||
|
// 读取图片
|
||||||
|
$image = Image::open($file);
|
||||||
|
// 生成缩略图
|
||||||
|
$thumb_type = $thumb_type == '' ? config('upload_image_thumb_type') : $thumb_type;
|
||||||
|
$image->thumb($thumb_max_width, $thumb_max_height, $thumb_type);
|
||||||
|
// 保存缩略图
|
||||||
|
$thumb_path = config('upload_path') . DIRECTORY_SEPARATOR . 'images/' . $dir . '/thumb/';
|
||||||
|
if (!is_dir($thumb_path)) {
|
||||||
|
mkdir($thumb_path, 0766, true);
|
||||||
|
}
|
||||||
|
$thumb_path_name = $thumb_path. $save_name;
|
||||||
|
$image->save($thumb_path_name);
|
||||||
|
$thumb_path_name = 'uploads/images/' . $dir . '/thumb/' . $save_name;
|
||||||
|
return $thumb_path_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加水印
|
||||||
|
* @param string $file 要添加水印的文件路径
|
||||||
|
* @param string $watermark_img 水印图片id
|
||||||
|
* @param string $watermark_pos 水印位置
|
||||||
|
* @param string $watermark_alpha 水印透明度
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function create_water($file = '', $watermark_img = '', $watermark_pos = '', $watermark_alpha = '')
|
||||||
|
{
|
||||||
|
$path = model('admin/attachment')->getFilePath($watermark_img, 1);
|
||||||
|
$thumb_water_pic = realpath(Env::get('root_path') . 'public/' . $path);
|
||||||
|
if (is_file($thumb_water_pic)) {
|
||||||
|
// 读取图片
|
||||||
|
$image = Image::open($file);
|
||||||
|
// 添加水印
|
||||||
|
$watermark_pos = $watermark_pos == '' ? config('upload_thumb_water_position') : $watermark_pos;
|
||||||
|
$watermark_alpha = $watermark_alpha == '' ? config('upload_thumb_water_alpha') : $watermark_alpha;
|
||||||
|
$image->water($thumb_water_pic, $watermark_pos, $watermark_alpha);
|
||||||
|
// 保存水印图片,覆盖原图
|
||||||
|
$image->save($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传成功信息
|
||||||
|
* @param $from
|
||||||
|
* @param string $file_path
|
||||||
|
* @param string $file_name
|
||||||
|
* @param string $file_id
|
||||||
|
* @param string $callback
|
||||||
|
* @return string|\think\response\Json
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function uploadSuccess($from, $file_path = '', $file_name = '', $file_id = '', $callback = '')
|
||||||
|
{
|
||||||
|
switch ($from) {
|
||||||
|
case 'wangeditor':
|
||||||
|
return $file_path;
|
||||||
|
break;
|
||||||
|
case 'ueditor':
|
||||||
|
return json([
|
||||||
|
"state" => "SUCCESS", // 上传状态,上传成功时必须返回"SUCCESS"
|
||||||
|
"url" => $file_path, // 返回的地址
|
||||||
|
"title" => $file_name, // 附件名
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'editormd':
|
||||||
|
return json([
|
||||||
|
"success" => 1,
|
||||||
|
"message" => '上传成功',
|
||||||
|
"url" => $file_path,
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'ckeditor':
|
||||||
|
return ck_js($callback, $file_path);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return json([
|
||||||
|
'code' => 1,
|
||||||
|
'info' => '上传成功',
|
||||||
|
'class' => 'success',
|
||||||
|
'id' => $file_id,
|
||||||
|
'path' => $file_path
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传错误信息
|
||||||
|
* @param $from
|
||||||
|
* @param string $msg
|
||||||
|
* @param string $callback
|
||||||
|
* @return string|\think\response\Json
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function uploadError($from, $msg = '', $callback = '')
|
||||||
|
{
|
||||||
|
switch ($from) {
|
||||||
|
case 'wangeditor':
|
||||||
|
return "error|".$msg;
|
||||||
|
break;
|
||||||
|
case 'ueditor':
|
||||||
|
return json(['state' => $msg]);
|
||||||
|
break;
|
||||||
|
case 'editormd':
|
||||||
|
return json(["success" => 0, "message" => $msg]);
|
||||||
|
break;
|
||||||
|
case 'ckeditor':
|
||||||
|
return ck_js($callback, '', $msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return json([
|
||||||
|
'code' => 0,
|
||||||
|
'class' => 'danger',
|
||||||
|
'info' => $msg
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历获取目录下的指定类型的附件
|
||||||
|
* @param string $path 路径
|
||||||
|
* @param string $allowFiles 允许查看的类型
|
||||||
|
* @param array $files 文件列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function getfiles($path = '', $allowFiles = '', &$files = array())
|
||||||
|
{
|
||||||
|
if (!is_dir($path)) return null;
|
||||||
|
if(substr($path, strlen($path) - 1) != '/') $path .= '/';
|
||||||
|
$handle = opendir($path);
|
||||||
|
while (false !== ($file = readdir($handle))) {
|
||||||
|
if ($file != '.' && $file != '..') {
|
||||||
|
$path2 = $path . $file;
|
||||||
|
if (is_dir($path2)) {
|
||||||
|
$this->getfiles($path2, $allowFiles, $files);
|
||||||
|
} else {
|
||||||
|
if (preg_match("/\.(".$allowFiles.")$/i", $file)) {
|
||||||
|
$files[] = array(
|
||||||
|
'url'=> str_replace("\\", "/", substr($path2, strlen($_SERVER['DOCUMENT_ROOT']))),
|
||||||
|
'mtime'=> filemtime($path2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用附件
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用附件
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置附件状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$ids = is_array($ids) ? implode(',', $ids) : $ids;
|
||||||
|
return parent::setStatus($type, ['attachment_'.$type, 'admin_attachment', 0, UID, $ids]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除附件
|
||||||
|
* @param string $ids 附件id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($ids = '')
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
if (empty($ids)) $this->error('缺少主键');
|
||||||
|
|
||||||
|
$files_path = AttachmentModel::where('id', 'in', $ids)->column('path,thumb', 'id');
|
||||||
|
|
||||||
|
foreach ($files_path as $value) {
|
||||||
|
$real_path = realpath(config('upload_path').'/../'.$value['path']);
|
||||||
|
$real_path_thumb = realpath(config('upload_path').'/../'.$value['thumb']);
|
||||||
|
|
||||||
|
if (is_file($real_path) && !unlink($real_path)) {
|
||||||
|
$this->error('删除失败');
|
||||||
|
}
|
||||||
|
if (is_file($real_path_thumb) && !unlink($real_path_thumb)) {
|
||||||
|
$this->error('删除缩略图失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AttachmentModel::where('id', 'in', $ids)->delete()) {
|
||||||
|
// 记录行为
|
||||||
|
$ids = is_array($ids) ? implode(',', $ids) : $ids;
|
||||||
|
action_log('attachment_delete', 'admin_attachment', 0, UID, $ids);
|
||||||
|
$this->success('删除成功');
|
||||||
|
} else {
|
||||||
|
$this->error('删除失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
return parent::quickEdit(['attachment_edit', 'admin_attachment', 0, UID, $id]);
|
||||||
|
}
|
||||||
|
}
|
281
application/admin/controller/Config.php
Normal file
281
application/admin/controller/Config.php
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Config as ConfigModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统配置控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Config extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 配置首页
|
||||||
|
* @param string $group 分组
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index($group = 'base')
|
||||||
|
{
|
||||||
|
cookie('__forward__', $_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
|
// 配置分组信息
|
||||||
|
$list_group = config('config_group');
|
||||||
|
$tab_list = [];
|
||||||
|
foreach ($list_group as $key => $value) {
|
||||||
|
$tab_list[$key]['title'] = $value;
|
||||||
|
$tab_list[$key]['url'] = url('index', ['group' => $key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
$map[] = ['group', '=', $group];
|
||||||
|
$map[] = ['status', 'egt', 0];
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('sort asc,id asc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = ConfigModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setPageTitle('配置管理') // 设置页面标题
|
||||||
|
->setTabNav($tab_list, $group) // 设置tab分页
|
||||||
|
->setSearch(['name' => '名称', 'title' => '标题']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['name', '名称', 'text.edit'],
|
||||||
|
['title', '标题', 'text.edit'],
|
||||||
|
['type', '类型', 'select', config('form_item_type')],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addValidate('Config', 'name,title') // 添加快捷编辑的验证器
|
||||||
|
->addOrder('name,title,status') // 添加标题字段排序
|
||||||
|
->addFilter('name,title') // 添加标题字段筛选
|
||||||
|
->addFilter('type', config('form_item_type')) // 添加标题字段筛选
|
||||||
|
->addFilterMap('name,title', ['group' => $group]) // 添加标题字段筛选条件
|
||||||
|
->addTopButton('add', ['href' => url('add', ['group' => $group])], true) // 添加单个顶部按钮
|
||||||
|
->addTopButtons('enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButton('edit', [], true)
|
||||||
|
->addRightButton('delete') // 批量添加右侧按钮
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增配置项
|
||||||
|
* @param string $group 分组
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add($group = '')
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Config');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
// 如果是快速联动
|
||||||
|
if ($data['type'] == 'linkages') {
|
||||||
|
$data['key'] = $data['key'] == '' ? 'id' : $data['key'];
|
||||||
|
$data['pid'] = $data['pid'] == '' ? 'pid' : $data['pid'];
|
||||||
|
$data['level'] = $data['level'] == '' ? '2' : $data['level'];
|
||||||
|
$data['option'] = $data['option'] == '' ? 'name' : $data['option'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($config = ConfigModel::create($data)) {
|
||||||
|
cache('system_config', null);
|
||||||
|
$forward = $this->request->param('_pop') == 1 ? null : cookie('__forward__');
|
||||||
|
// 记录行为
|
||||||
|
$details = '详情:分组('.$data['group'].')、类型('.$data['type'].')、标题('.$data['title'].')、名称('.$data['name'].')';
|
||||||
|
action_log('config_add', 'admin_config', $config['id'], UID, $details);
|
||||||
|
$this->success('新增成功', $forward);
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('新增')
|
||||||
|
->addRadio('group', '配置分组', '', config('config_group'), $group)
|
||||||
|
->addSelect('type', '配置类型', '', config('form_item_type'))
|
||||||
|
->addText('title', '配置标题', '一般由中文组成,仅用于显示')
|
||||||
|
->addText('name', '配置名称', '由英文字母和下划线组成,如 <code>web_site_title</code>,调用方法:<code>config(\'web_site_title\')</code>')
|
||||||
|
->addTextarea('value', '配置值', '该配置的具体内容')
|
||||||
|
->addTextarea('options', '配置项', '用于单选、多选、下拉、联动等类型')
|
||||||
|
->addText('ajax_url', '异步请求地址', "如请求的地址是 <code>url('ajax/getCity')</code>,那么只需填写 <code>ajax/getCity</code>,或者直接填写以 <code>http</code>开头的url地址")
|
||||||
|
->addText('next_items', '下一级联动下拉框的表单名', "与当前有关联的下级联动下拉框名,多个用逗号隔开,如:area,other")
|
||||||
|
->addText('param', '请求参数名', "联动下拉框请求参数名,默认为配置名称")
|
||||||
|
->addNumber('level', '级别', '需要显示的级别数量,默认为2', 2, 2, 4)
|
||||||
|
->addText('table', '表名', '要查询的表,里面必须含有id、name、pid三个字段,其中id和name字段可在下面重新定义')
|
||||||
|
->addText('pid', '父级id字段名', '即表中的父级ID字段名,如果表中的主键字段名为pid则可不填写')
|
||||||
|
->addText('key', '键字段名', '即表中的主键字段名,如果表中的主键字段名为id则可不填写')
|
||||||
|
->addText('option', '值字段名', '下拉菜单显示的字段名,如果表中的该字段名为name则可不填写')
|
||||||
|
->addText('ak', 'APPKEY', '百度编辑器APPKEY')
|
||||||
|
->addText('format', '格式')
|
||||||
|
->addText('tips', '配置说明', '该配置的具体说明')
|
||||||
|
->addText('sort', '排序', '', 100)
|
||||||
|
->setTrigger('type', 'linkage', 'ajax_url,next_items,param')
|
||||||
|
->setTrigger('type', 'linkages', 'table,pid,level,key,option')
|
||||||
|
->setTrigger('type', 'bmap', 'ak')
|
||||||
|
->setTrigger('type', 'masked,date,time,datetime', 'format')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param int $id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function edit($id = 0)
|
||||||
|
{
|
||||||
|
if ($id === 0) $this->error('参数错误');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Config');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
// 如果是快速联动
|
||||||
|
if ($data['type'] == 'linkages') {
|
||||||
|
$data['key'] = $data['key'] == '' ? 'id' : $data['key'];
|
||||||
|
$data['pid'] = $data['pid'] == '' ? 'pid' : $data['pid'];
|
||||||
|
$data['level'] = $data['level'] == '' ? '2' : $data['level'];
|
||||||
|
$data['option'] = $data['option'] == '' ? 'name' : $data['option'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原配置内容
|
||||||
|
$config = ConfigModel::where('id', $id)->find();
|
||||||
|
$details = '原数据:分组('.$config['group'].')、类型('.$config['type'].')、标题('.$config['title'].')、名称('.$config['name'].')';
|
||||||
|
|
||||||
|
if ($config = ConfigModel::update($data)) {
|
||||||
|
cache('system_config', null);
|
||||||
|
$forward = $this->request->param('_pop') == 1 ? null : cookie('__forward__');
|
||||||
|
// 记录行为
|
||||||
|
action_log('config_edit', 'admin_config', $config['id'], UID, $details);
|
||||||
|
$this->success('编辑成功', $forward, '_parent_reload');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$info = ConfigModel::get($id);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('编辑')
|
||||||
|
->addHidden('id')
|
||||||
|
->addRadio('group', '配置分组', '', config('config_group'))
|
||||||
|
->addSelect('type', '配置类型', '', config('form_item_type'))
|
||||||
|
->addText('title', '配置标题', '一般由中文组成,仅用于显示')
|
||||||
|
->addText('name', '配置名称', '由英文字母和下划线组成,如 <code>web_site_title</code>,调用方法:<code>config(\'web_site_title\')</code>')
|
||||||
|
->addTextarea('value', '配置值', '该配置的具体内容')
|
||||||
|
->addTextarea('options', '配置项', '用于单选、多选、下拉、联动等类型')
|
||||||
|
->addText('ajax_url', '异步请求地址', "如请求的地址是 <code>url('ajax/getCity')</code>,那么只需填写 <code>ajax/getCity</code>,或者直接填写以 <code>http</code>开头的url地址")
|
||||||
|
->addText('next_items', '下一级联动下拉框的表单名', "与当前有关联的下级联动下拉框名,多个用逗号隔开,如:area,other")
|
||||||
|
->addText('param', '请求参数名', "联动下拉框请求参数名,默认为配置名称")
|
||||||
|
->addNumber('level', '级别', '需要显示的级别数量,默认为2', 2, 2, 4)
|
||||||
|
->addText('table', '表名', '要查询的表,里面必须含有id、name、pid三个字段,其中id和name字段可在下面重新定义')
|
||||||
|
->addText('pid', '父级id字段名', '即表中的父级ID字段名,如果表中的主键字段名为pid则可不填写')
|
||||||
|
->addText('key', '键字段名', '即表中的主键字段名,如果表中的主键字段名为id则可不填写')
|
||||||
|
->addText('option', '值字段名', '下拉菜单显示的字段名,如果表中的该字段名为name则可不填写')
|
||||||
|
->addText('ak', 'APPKEY', '百度编辑器APPKEY')
|
||||||
|
->addText('format', '格式')
|
||||||
|
->addText('tips', '配置说明', '该配置的具体说明')
|
||||||
|
->addText('sort', '排序', '', 100)
|
||||||
|
->setTrigger('type', 'linkage', 'ajax_url,next_items,param')
|
||||||
|
->setTrigger('type', 'linkages', 'table,pid,level,key,option')
|
||||||
|
->setTrigger('type', 'bmap', 'ak')
|
||||||
|
->setTrigger('type', 'masked,date,time,datetime', 'format')
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配置
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用配置
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用配置
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置配置状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$uid_delete = is_array($ids) ? '' : $ids;
|
||||||
|
$ids = ConfigModel::where('id', 'in', $ids)->column('title');
|
||||||
|
return parent::setStatus($type, ['config_'.$type, 'admin_config', $uid_delete, UID, implode('、', $ids)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$config = ConfigModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $config . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['config_edit', 'admin_config', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
366
application/admin/controller/Database.php
Normal file
366
application/admin/controller/Database.php
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use think\Db;
|
||||||
|
use util\Database as DatabaseModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库管理
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Database extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 数据库管理
|
||||||
|
* @param string $group 分组
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function index($group = 'export')
|
||||||
|
{
|
||||||
|
// 配置分组信息
|
||||||
|
$list_group = ['export' =>'备份数据库', 'import' => '还原数据库'];
|
||||||
|
$tab_list = [];
|
||||||
|
foreach ($list_group as $key => $value) {
|
||||||
|
$tab_list[$key]['title'] = $value;
|
||||||
|
$tab_list[$key]['url'] = url('index', ['group' => $key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($group) {
|
||||||
|
case 'export':
|
||||||
|
$data_list = Db::query("SHOW TABLE STATUS");
|
||||||
|
$data_list = array_map('array_change_key_case', $data_list);
|
||||||
|
|
||||||
|
// 自定义按钮
|
||||||
|
$btn_export = [
|
||||||
|
'title' => '立即备份',
|
||||||
|
'icon' => 'fa fa-fw fa-copy',
|
||||||
|
'class' => 'btn btn-primary ajax-post confirm',
|
||||||
|
'href' => url('export')
|
||||||
|
];
|
||||||
|
$btn_optimize_all = [
|
||||||
|
'title' => '优化表',
|
||||||
|
'icon' => 'fa fa-fw fa-cogs',
|
||||||
|
'class' => 'btn btn-success ajax-post',
|
||||||
|
'href' => url('optimize')
|
||||||
|
];
|
||||||
|
$btn_repair_all = [
|
||||||
|
'title' => '修复表',
|
||||||
|
'icon' => 'fa fa-fw fa-wrench',
|
||||||
|
'class' => 'btn btn-success ajax-post',
|
||||||
|
'href' => url('repair')
|
||||||
|
];
|
||||||
|
$btn_optimize = [
|
||||||
|
'title' => '优化表',
|
||||||
|
'icon' => 'fa fa-fw fa-cogs',
|
||||||
|
'class' => 'btn btn-xs btn-default ajax-get',
|
||||||
|
'href' => url('optimize', ['ids' => '__id__'])
|
||||||
|
];
|
||||||
|
$btn_repair = [
|
||||||
|
'title' => '修复表',
|
||||||
|
'icon' => 'fa fa-fw fa-wrench',
|
||||||
|
'class' => 'btn btn-xs btn-default ajax-get',
|
||||||
|
'href' => url('repair', ['ids' => '__id__'])
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setPageTitle('数据库管理') // 设置页面标题
|
||||||
|
->setPrimaryKey('name')
|
||||||
|
->setTabNav($tab_list, $group) // 设置tab分页
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['name', '表名'],
|
||||||
|
['rows', '行数'],
|
||||||
|
['data_length', '大小', 'byte'],
|
||||||
|
['data_free', '冗余', 'byte'],
|
||||||
|
['comment', '备注'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButton('custom', $btn_export) // 添加单个顶部按钮
|
||||||
|
->addTopButton('custom', $btn_optimize_all) // 添加单个顶部按钮
|
||||||
|
->addTopButton('custom', $btn_repair_all) // 添加单个顶部按钮
|
||||||
|
->addRightButton('custom', $btn_optimize) // 添加右侧按钮
|
||||||
|
->addRightButton('custom', $btn_repair) // 添加右侧按钮
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
break;
|
||||||
|
case 'import':
|
||||||
|
// 列出备份文件列表
|
||||||
|
$path = config('data_backup_path');
|
||||||
|
if(!is_dir($path)){
|
||||||
|
mkdir($path, 0755, true);
|
||||||
|
}
|
||||||
|
$path = realpath($path);
|
||||||
|
$flag = \FilesystemIterator::KEY_AS_FILENAME;
|
||||||
|
$glob = new \FilesystemIterator($path, $flag);
|
||||||
|
|
||||||
|
$data_list = [];
|
||||||
|
foreach ($glob as $name => $file) {
|
||||||
|
if(preg_match('/^\d{8,8}-\d{6,6}-\d+\.sql(?:\.gz)?$/', $name)){
|
||||||
|
$name = sscanf($name, '%4s%2s%2s-%2s%2s%2s-%d');
|
||||||
|
|
||||||
|
$date = "{$name[0]}-{$name[1]}-{$name[2]}";
|
||||||
|
$time = "{$name[3]}:{$name[4]}:{$name[5]}";
|
||||||
|
$part = $name[6];
|
||||||
|
|
||||||
|
if(isset($data_list["{$date} {$time}"])){
|
||||||
|
$info = $data_list["{$date} {$time}"];
|
||||||
|
$info['part'] = max($info['part'], $part);
|
||||||
|
$info['size'] = $info['size'] + $file->getSize();
|
||||||
|
} else {
|
||||||
|
$info['part'] = $part;
|
||||||
|
$info['size'] = $file->getSize();
|
||||||
|
}
|
||||||
|
$extension = strtoupper(pathinfo($file->getFilename(), PATHINFO_EXTENSION));
|
||||||
|
$info['compress'] = ($extension === 'SQL') ? '-' : $extension;
|
||||||
|
$info['time'] = strtotime("{$date} {$time}");
|
||||||
|
$info['name'] = $info['time'];
|
||||||
|
|
||||||
|
$data_list["{$date} {$time}"] = $info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data_list = !empty($data_list) ? array_values($data_list) : $data_list;
|
||||||
|
|
||||||
|
// 自定义按钮
|
||||||
|
$btn_import = [
|
||||||
|
'title' => '还原',
|
||||||
|
'icon' => 'fa fa-fw fa-reply',
|
||||||
|
'class' => 'btn btn-xs btn-default ajax-get confirm',
|
||||||
|
'href' => url('import', ['time' => '__id__'])
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setPageTitle('数据库管理') // 设置页面标题
|
||||||
|
->setPrimaryKey('time')
|
||||||
|
->hideCheckbox()
|
||||||
|
->setTabNav($tab_list, $group) // 设置tab分页
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['name', '备份名称', 'datetime', '', 'Ymd-His'],
|
||||||
|
['part', '卷数'],
|
||||||
|
['compress', '压缩'],
|
||||||
|
['size', '数据大小', 'byte'],
|
||||||
|
['time', '备份时间', 'datetime', '', 'Y-m-d H:i:s'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addRightButton('custom', $btn_import) // 添加右侧按钮
|
||||||
|
->addRightButton('delete') // 添加右侧按钮
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备份数据库(参考onthink 麦当苗儿 <zuojiazi@vip.qq.com>)
|
||||||
|
* @param null|array $ids 表名
|
||||||
|
* @param integer $start 起始行数
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function export($ids = null, $start = 0)
|
||||||
|
{
|
||||||
|
$tables = $ids;
|
||||||
|
if ($this->request->isPost() && !empty($tables) && is_array($tables)) {
|
||||||
|
// 初始化
|
||||||
|
$path = config('data_backup_path');
|
||||||
|
if(!is_dir($path)){
|
||||||
|
mkdir($path, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取备份配置
|
||||||
|
$config = array(
|
||||||
|
'path' => realpath($path) . DIRECTORY_SEPARATOR,
|
||||||
|
'part' => config('data_backup_part_size'),
|
||||||
|
'compress' => config('data_backup_compress'),
|
||||||
|
'level' => config('data_backup_compress_level'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 检查是否有正在执行的任务
|
||||||
|
$lock = "{$config['path']}backup.lock";
|
||||||
|
if(is_file($lock)){
|
||||||
|
$this->error('检测到有一个备份任务正在执行,请稍后再试!');
|
||||||
|
} else {
|
||||||
|
// 创建锁文件
|
||||||
|
file_put_contents($lock, $this->request->time());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查备份目录是否可写
|
||||||
|
is_writeable($config['path']) || $this->error('备份目录不存在或不可写,请检查后重试!');
|
||||||
|
|
||||||
|
// 生成备份文件信息
|
||||||
|
$file = array(
|
||||||
|
'name' => date('Ymd-His', $this->request->time()),
|
||||||
|
'part' => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 创建备份文件
|
||||||
|
$Database = new DatabaseModel($file, $config);
|
||||||
|
if(false !== $Database->create()){
|
||||||
|
// 备份指定表
|
||||||
|
foreach ($tables as $table) {
|
||||||
|
$start = $Database->backup($table, $start);
|
||||||
|
while (0 !== $start) {
|
||||||
|
if (false === $start) { // 出错
|
||||||
|
$this->error('备份出错!');
|
||||||
|
}
|
||||||
|
$start = $Database->backup($table, $start[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 备份完成,删除锁定文件
|
||||||
|
unlink($lock);
|
||||||
|
// 记录行为
|
||||||
|
action_log('database_export', 'database', 0, UID, implode(',', $tables));
|
||||||
|
$this->success('备份完成!');
|
||||||
|
} else {
|
||||||
|
$this->error('初始化失败,备份文件创建失败!');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error('参数错误!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 还原数据库(参考onthink 麦当苗儿 <zuojiazi@vip.qq.com>)
|
||||||
|
* @param int $time 文件时间戳
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function import($time = 0)
|
||||||
|
{
|
||||||
|
if ($time === 0) $this->error('参数错误!');
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
$name = date('Ymd-His', $time) . '-*.sql*';
|
||||||
|
$path = realpath(config('data_backup_path')) . DIRECTORY_SEPARATOR . $name;
|
||||||
|
$files = glob($path);
|
||||||
|
$list = array();
|
||||||
|
foreach($files as $name){
|
||||||
|
$basename = basename($name);
|
||||||
|
$match = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d');
|
||||||
|
$gz = preg_match('/^\d{8,8}-\d{6,6}-\d+\.sql.gz$/', $basename);
|
||||||
|
$list[$match[6]] = array($match[6], $name, $gz);
|
||||||
|
}
|
||||||
|
ksort($list);
|
||||||
|
|
||||||
|
// 检测文件正确性
|
||||||
|
$last = end($list);
|
||||||
|
if(count($list) === $last[0]){
|
||||||
|
foreach ($list as $item) {
|
||||||
|
$config = [
|
||||||
|
'path' => realpath(config('data_backup_path')) . DIRECTORY_SEPARATOR,
|
||||||
|
'compress' => $item[2]
|
||||||
|
];
|
||||||
|
$Database = new DatabaseModel($item, $config);
|
||||||
|
$start = $Database->import(0);
|
||||||
|
|
||||||
|
// 循环导入数据
|
||||||
|
while (0 !== $start) {
|
||||||
|
if (false === $start) { // 出错
|
||||||
|
$this->error('还原数据出错!');
|
||||||
|
}
|
||||||
|
$start = $Database->import($start[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 记录行为
|
||||||
|
action_log('database_import', 'database', 0, UID, date('Ymd-His', $time));
|
||||||
|
$this->success('还原完成!');
|
||||||
|
} else {
|
||||||
|
$this->error('备份文件可能已经损坏,请检查!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优化表
|
||||||
|
* @param null|string|array $ids 表名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function optimize($ids = null)
|
||||||
|
{
|
||||||
|
$tables = $ids;
|
||||||
|
if($tables) {
|
||||||
|
if(is_array($tables)){
|
||||||
|
$tables = implode('`,`', $tables);
|
||||||
|
$list = Db::query("OPTIMIZE TABLE `{$tables}`");
|
||||||
|
|
||||||
|
if($list){
|
||||||
|
// 记录行为
|
||||||
|
action_log('database_optimize', 'database', 0, UID, "`{$tables}`");
|
||||||
|
$this->success("数据表优化完成!");
|
||||||
|
} else {
|
||||||
|
$this->error("数据表优化出错请重试!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$list = Db::query("OPTIMIZE TABLE `{$tables}`");
|
||||||
|
if($list){
|
||||||
|
// 记录行为
|
||||||
|
action_log('database_optimize', 'database', 0, UID, $tables);
|
||||||
|
$this->success("数据表'{$tables}'优化完成!");
|
||||||
|
} else {
|
||||||
|
$this->error("数据表'{$tables}'优化出错请重试!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error("请选择要优化的表!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修复表
|
||||||
|
* @param null|string|array $ids 表名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function repair($ids = null)
|
||||||
|
{
|
||||||
|
$tables = $ids;
|
||||||
|
if($tables) {
|
||||||
|
if(is_array($tables)){
|
||||||
|
$tables = implode('`,`', $tables);
|
||||||
|
$list = Db::query("REPAIR TABLE `{$tables}`");
|
||||||
|
|
||||||
|
if($list){
|
||||||
|
// 记录行为
|
||||||
|
action_log('database_repair', 'database', 0, UID, "`{$tables}`");
|
||||||
|
$this->success("数据表修复完成!");
|
||||||
|
} else {
|
||||||
|
$this->error("数据表修复出错请重试!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$list = Db::query("REPAIR TABLE `{$tables}`");
|
||||||
|
if($list){
|
||||||
|
// 记录行为
|
||||||
|
action_log('database_repair', 'database', 0, UID, $tables);
|
||||||
|
$this->success("数据表'{$tables}'修复完成!");
|
||||||
|
} else {
|
||||||
|
$this->error("数据表'{$tables}'修复出错请重试!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error("请指定要修复的表!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除备份文件
|
||||||
|
* @param int $ids 备份时间
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function delete($ids = 0)
|
||||||
|
{
|
||||||
|
if ($ids == 0) $this->error('参数错误!');
|
||||||
|
|
||||||
|
$name = date('Ymd-His', $ids) . '-*.sql*';
|
||||||
|
$path = realpath(config('data_backup_path')) . DIRECTORY_SEPARATOR . $name;
|
||||||
|
array_map("unlink", glob($path));
|
||||||
|
if(count(glob($path))){
|
||||||
|
$this->error('备份文件删除失败,请检查权限!');
|
||||||
|
} else {
|
||||||
|
// 记录行为
|
||||||
|
action_log('database_backup_delete', 'database', 0, UID, date('Ymd-His', $ids));
|
||||||
|
$this->success('备份文件删除成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
234
application/admin/controller/Hook.php
Normal file
234
application/admin/controller/Hook.php
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\model\HookPlugin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Hook as HookModel;
|
||||||
|
use app\admin\model\HookPlugin as HookPluginModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钩子控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Hook extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 钩子管理
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$map = $this->getMap();
|
||||||
|
$order = $this->getOrder();
|
||||||
|
|
||||||
|
// 数据列表
|
||||||
|
$data_list = HookModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
// 分页数据
|
||||||
|
$page = $data_list->render();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setPageTitle('钩子管理') // 设置页面标题
|
||||||
|
->setSearch(['name' => '钩子名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['name', '名称'],
|
||||||
|
['description', '描述'],
|
||||||
|
['plugin', '所属插件', 'callback', function($plugin){
|
||||||
|
return $plugin == '' ? '系统' : $plugin;
|
||||||
|
}],
|
||||||
|
['system', '系统钩子', 'yesno'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addOrder('name,status')
|
||||||
|
->addTopButtons('add,enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons('edit,delete') // 批量添加右侧按钮
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->setPages($page) // 设置分页数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
$data['system'] = 1;
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Hook');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($hook = HookModel::create($data)) {
|
||||||
|
cache('hook_plugins', null);
|
||||||
|
// 记录行为
|
||||||
|
action_log('hook_add', 'admin_hook', $hook['id'], UID, $data['name']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('新增')
|
||||||
|
->addText('name', '钩子名称', '由字母和下划线组成,如:<code>page_tips</code>')
|
||||||
|
->addText('description', '钩子描述')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param int $id 钩子id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = 0)
|
||||||
|
{
|
||||||
|
if ($id === 0) $this->error('参数错误');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Hook');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($hook = HookModel::update($data)) {
|
||||||
|
// 调整插件顺序
|
||||||
|
if ($data['sort'] != '') {
|
||||||
|
HookPluginModel::sort($data['name'], $data['sort']);
|
||||||
|
}
|
||||||
|
cache('hook_plugins', null);
|
||||||
|
// 记录行为
|
||||||
|
action_log('hook_edit', 'admin_hook', $hook['id'], UID, $data['name']);
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$info = HookModel::get($id);
|
||||||
|
|
||||||
|
// 该钩子的所有插件
|
||||||
|
$hooks = HookPluginModel::where('hook', $info['name'])->order('sort')->column('plugin');
|
||||||
|
$hooks = parse_array($hooks);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('编辑')
|
||||||
|
->addHidden('id')
|
||||||
|
->addText('name', '钩子名称', '由字母和下划线组成,如:<code>page_tips</code>')
|
||||||
|
->addText('description', '钩子描述')
|
||||||
|
->addSort('sort', '插件排序', '', $hooks)
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑(启用/禁用)
|
||||||
|
* @param string $status 状态
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($status = '')
|
||||||
|
{
|
||||||
|
$id = $this->request->post('pk');
|
||||||
|
$status = $this->request->param('value');
|
||||||
|
$hook_name = HookModel::where('id', $id)->value('name');
|
||||||
|
|
||||||
|
if (false === HookPluginModel::where('hook', $hook_name)->setField('status', $status == 'true' ? 1 : 0)) {
|
||||||
|
$this->error('操作失败,请重试');
|
||||||
|
}
|
||||||
|
cache('hook_plugins', null);
|
||||||
|
$details = $status == 'true' ? '启用钩子' : '禁用钩子';
|
||||||
|
return parent::quickEdit(['hook_edit', 'admin_hook', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 禁用
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除钩子
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$map = [
|
||||||
|
['id', 'in', $ids],
|
||||||
|
['system', '=', 1],
|
||||||
|
];
|
||||||
|
if (HookModel::where($map)->find()) {
|
||||||
|
$this->error('禁止删除系统钩子');
|
||||||
|
}
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置状态
|
||||||
|
* @param string $type 类型
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->param('ids/a');
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$hook_name = HookModel::where('id', $id)->value('name');
|
||||||
|
if (false === HookPluginModel::where('hook', $hook_name)->setField('status', $type == 'enable' ? 1 : 0)) {
|
||||||
|
$this->error('操作失败,请重试');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache('hook_plugins', null);
|
||||||
|
$hook_delete = is_array($ids) ? '' : $ids;
|
||||||
|
$hook_names = HookModel::where('id', 'in', $ids)->column('name');
|
||||||
|
return parent::setStatus($type, ['hook_'.$type, 'admin_hook', $hook_delete, UID, implode('、', $hook_names)]);
|
||||||
|
}
|
||||||
|
}
|
223
application/admin/controller/Icon.php
Normal file
223
application/admin/controller/Icon.php
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Icon as IconModel;
|
||||||
|
use app\admin\model\IconList as IconListModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Icon extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 图标列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$data_list = IconModel::where($this->getMap())
|
||||||
|
->order($this->getOrder('id DESC'))
|
||||||
|
->paginate();
|
||||||
|
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->addTopButtons('add,enable,disable,delete')
|
||||||
|
->addRightButton('list', [
|
||||||
|
'title' => '图标列表',
|
||||||
|
'icon' => 'fa fa-list',
|
||||||
|
'href' => url('items', ['id' => '__id__'])
|
||||||
|
])
|
||||||
|
->addRightButton('reload', [
|
||||||
|
'title' => '更新图标',
|
||||||
|
'icon' => 'fa fa-refresh',
|
||||||
|
'class' => 'btn btn-xs btn-default ajax-get confirm',
|
||||||
|
'href' => url('reload', ['id' => '__id__'])
|
||||||
|
])
|
||||||
|
->addRightButton('delete')
|
||||||
|
->setSearch('name')
|
||||||
|
->addColumns([
|
||||||
|
['id', 'ID'],
|
||||||
|
['name', '名称', 'text.edit'],
|
||||||
|
['url', '链接', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['right_button', '操作', 'btn'],
|
||||||
|
])
|
||||||
|
->setRowList($data_list)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post('', null, 'trim');
|
||||||
|
$data['name'] == '' && $this->error('请填写名称');
|
||||||
|
$data['url'] == '' && $this->error('请填写链接');
|
||||||
|
$data['create_time'] = $this->request->time();
|
||||||
|
$data['update_time'] = $this->request->time();
|
||||||
|
|
||||||
|
// 获取图标信息
|
||||||
|
$url = substr($data['url'], 0, 4) == 'http' ? $data['url'] : 'http:'.$data['url'];
|
||||||
|
$content = file_get_contents($url);
|
||||||
|
|
||||||
|
// 获取字体名
|
||||||
|
$font_family = '';
|
||||||
|
$pattern = '/font-family: "(.*)";/';
|
||||||
|
if (preg_match($pattern, $content, $match)) {
|
||||||
|
$font_family = $match[1];
|
||||||
|
} else {
|
||||||
|
$this->error('无法获取字体名');
|
||||||
|
}
|
||||||
|
|
||||||
|
$IconModel = new IconModel();
|
||||||
|
if ($id = $IconModel->insertGetId($data)) {
|
||||||
|
// 拉取图标列表
|
||||||
|
$pattern = '/\.(.*):before/';
|
||||||
|
if (preg_match_all($pattern, $content, $matches)) {
|
||||||
|
$icon_list = [];
|
||||||
|
foreach ($matches[1] as $match) {
|
||||||
|
$icon_list[] = [
|
||||||
|
'icon_id' => $id,
|
||||||
|
'title' => $match,
|
||||||
|
'class' => $font_family . ' ' . $match,
|
||||||
|
'code' => $match,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$IconListModel = new IconListModel();
|
||||||
|
if ($IconListModel->saveAll($icon_list)) {
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$IconModel->where('id', $id)->delete();
|
||||||
|
$this->error('图标添加失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['text', 'name', '名称', '可填写中文'],
|
||||||
|
['text', 'url', '链接', '如://at.alicdn.com/t/font_588968_z5hsg7xluoh41jor.css'],
|
||||||
|
])
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标列表
|
||||||
|
* @param string $id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function items($id = '')
|
||||||
|
{
|
||||||
|
$data_list = IconListModel::where($this->getMap())
|
||||||
|
->order($this->getOrder('id DESC'))
|
||||||
|
->where('icon_id', $id)
|
||||||
|
->paginate();
|
||||||
|
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setTableName('admin_icon_list')
|
||||||
|
->addTopButtons('back')
|
||||||
|
->addTopButton('add', [
|
||||||
|
'title' => '更新图标',
|
||||||
|
'icon' => 'fa fa-refresh',
|
||||||
|
'class' => 'btn btn-primary ajax-get confirm',
|
||||||
|
'href' => url('reload', ['id' => $id])
|
||||||
|
])
|
||||||
|
->setSearch('title,code')
|
||||||
|
->addColumns([
|
||||||
|
['icon', '图标', 'callback', function($data){
|
||||||
|
return '<i class="'.$data['class'].'"></i>';
|
||||||
|
}, '__data__'],
|
||||||
|
['title', '图标标题', 'text.edit'],
|
||||||
|
['code', '图标关键词', 'text.edit'],
|
||||||
|
['class', '图标类名'],
|
||||||
|
])
|
||||||
|
->setRowList($data_list)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新图标
|
||||||
|
* @param string $id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function reload($id = '')
|
||||||
|
{
|
||||||
|
$icon = IconModel::get($id);
|
||||||
|
// 获取图标信息
|
||||||
|
$url = substr($icon['url'], 0, 4) == 'http' ? $icon['url'] : 'http:'.$icon['url'];
|
||||||
|
$content = file_get_contents($url);
|
||||||
|
|
||||||
|
// 获取字体名
|
||||||
|
$font_family = '';
|
||||||
|
$pattern = '/font-family: "(.*)";/';
|
||||||
|
if (preg_match($pattern, $content, $match)) {
|
||||||
|
$font_family = $match[1];
|
||||||
|
} else {
|
||||||
|
$this->error('无法获取字体名');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拉取图标列表
|
||||||
|
$pattern = '/\.(.*):before/';
|
||||||
|
if (preg_match_all($pattern, $content, $matches)) {
|
||||||
|
$icon_list = [];
|
||||||
|
foreach ($matches[1] as $match) {
|
||||||
|
$icon_list[] = [
|
||||||
|
'icon_id' => $id,
|
||||||
|
'title' => $match,
|
||||||
|
'class' => $font_family . ' ' . $match,
|
||||||
|
'code' => $match,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$IconListModel = new IconListModel();
|
||||||
|
$IconListModel->where('icon_id', $id)->delete();
|
||||||
|
if ($IconListModel->saveAll($icon_list)) {
|
||||||
|
$this->success('更新成功');
|
||||||
|
} else {
|
||||||
|
$this->error('图标添加失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->success('更新成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除图标库
|
||||||
|
* @param string $ids
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function delete($ids = '')
|
||||||
|
{
|
||||||
|
$ids == '' && $this->error('请选择要删除的数据');
|
||||||
|
$ids = (array)$ids;
|
||||||
|
|
||||||
|
// 删除图标列表
|
||||||
|
if (false !== IconListModel::where('icon_id', 'in', $ids)->delete()) {
|
||||||
|
// 删除图标库
|
||||||
|
if (false !== IconModel::where('id', 'in', $ids)->delete()) {
|
||||||
|
$this->success('删除成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->error('删除失败');
|
||||||
|
}
|
||||||
|
}
|
25
application/admin/controller/Ie.php
Normal file
25
application/admin/controller/Ie.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\controller\Common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ie提示页面控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Ie extends Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 显示ie提示
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function index(){
|
||||||
|
// ie浏览器判断
|
||||||
|
if (get_browser_type() == 'ie') {
|
||||||
|
return $this->fetch();
|
||||||
|
} else {
|
||||||
|
$this->redirect('admin/index/index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
157
application/admin/controller/Index.php
Normal file
157
application/admin/controller/Index.php
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use think\facade\Cache;
|
||||||
|
use think\facade\Env;
|
||||||
|
use think\helper\Hash;
|
||||||
|
use think\Db;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\user\model\User as UserModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台默认控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Index extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 后台首页
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$admin_pass = Db::name('admin_user')->where('id', 1)->value('password');
|
||||||
|
|
||||||
|
if (UID == 1 && $admin_pass && Hash::check('admin', $admin_pass)) {
|
||||||
|
$this->assign('default_pass', 1);
|
||||||
|
}
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空系统缓存
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function wipeCache()
|
||||||
|
{
|
||||||
|
$wipe_cache_type = config('wipe_cache_type');
|
||||||
|
if (!empty($wipe_cache_type)) {
|
||||||
|
foreach ($wipe_cache_type as $item) {
|
||||||
|
switch ($item) {
|
||||||
|
case 'TEMP_PATH':
|
||||||
|
array_map('unlink', glob(Env::get('runtime_path'). 'temp/*.*'));
|
||||||
|
break;
|
||||||
|
case 'LOG_PATH':
|
||||||
|
$dirs = (array) glob(Env::get('runtime_path') . 'log/*');
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
array_map('unlink', glob($dir . '/*.log'));
|
||||||
|
}
|
||||||
|
array_map('rmdir', $dirs);
|
||||||
|
break;
|
||||||
|
case 'CACHE_PATH':
|
||||||
|
array_map('unlink', glob(Env::get('runtime_path'). 'cache/*.*'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cache::clear();
|
||||||
|
$this->success('清空成功');
|
||||||
|
} else {
|
||||||
|
$this->error('请在系统设置中选择需要清除的缓存类型');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 个人设置
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function profile()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
$data['nickname'] == '' && $this->error('昵称不能为空');
|
||||||
|
$data['id'] = UID;
|
||||||
|
|
||||||
|
// 如果没有填写密码,则不更新密码
|
||||||
|
if ($data['password'] == '') {
|
||||||
|
unset($data['password']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$UserModel = new UserModel();
|
||||||
|
if ($user = $UserModel->allowField(['nickname', 'email', 'password', 'mobile', 'avatar'])->update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('user_edit', 'admin_user', UID, UID, get_nickname(UID));
|
||||||
|
$this->success('编辑成功');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$info = UserModel::where('id', UID)->field('password', true)->find();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([ // 批量添加表单项
|
||||||
|
['static', 'username', '用户名', '不可更改'],
|
||||||
|
['text', 'nickname', '昵称', '可以是中文'],
|
||||||
|
['text', 'email', '邮箱', ''],
|
||||||
|
['password', 'password', '密码', '必填,6-20位'],
|
||||||
|
['text', 'mobile', '手机号'],
|
||||||
|
['image', 'avatar', '头像']
|
||||||
|
])
|
||||||
|
->setFormData($info) // 设置表单数据
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查版本更新
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\response\Json
|
||||||
|
* @throws \think\db\exception\BindParamException
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function checkUpdate()
|
||||||
|
{
|
||||||
|
$params = config('dolphin.');
|
||||||
|
$params['domain'] = request()->domain();
|
||||||
|
$params['website'] = config('web_site_title');
|
||||||
|
$params['ip'] = $_SERVER['SERVER_ADDR'];
|
||||||
|
$params['php_os'] = PHP_OS;
|
||||||
|
$params['php_version'] = PHP_VERSION;
|
||||||
|
$params['mysql_version'] = db()->query('select version() as version')[0]['version'];
|
||||||
|
$params['server_software'] = $_SERVER['SERVER_SOFTWARE'];
|
||||||
|
$params = http_build_query($params);
|
||||||
|
|
||||||
|
$opts = [
|
||||||
|
CURLOPT_TIMEOUT => 20,
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_URL => config('dolphin.product_update'),
|
||||||
|
CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
|
||||||
|
CURLOPT_POST => 1,
|
||||||
|
CURLOPT_POSTFIELDS => $params
|
||||||
|
];
|
||||||
|
|
||||||
|
// 初始化并执行curl请求
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt_array($ch, $opts);
|
||||||
|
$data = curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$result = json_decode($data, true);
|
||||||
|
|
||||||
|
if ($result['code'] == 1) {
|
||||||
|
return json([
|
||||||
|
'update' => '<a class="badge badge-primary" href="http://www.dolphinphp.com/download" target="_blank">有新版本:'.$result["version"].'</a>',
|
||||||
|
'auth' => $result['auth']
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'update' => '',
|
||||||
|
'auth' => $result['auth']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
application/admin/controller/Log.php
Normal file
84
application/admin/controller/Log.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Log as LogModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统日志控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Log extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 日志列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('admin_log.id desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = LogModel::getAll($map, $order);
|
||||||
|
// 分页数据
|
||||||
|
$page = $data_list->render();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setPageTitle('系统日志') // 设置页面标题
|
||||||
|
->setSearch(['admin_action.title' => '行为名称', 'admin_user.username' => '执行者', 'admin_module.title' => '所属模块']) // 设置搜索框
|
||||||
|
->hideCheckbox()
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', '编号'],
|
||||||
|
['title', '行为名称'],
|
||||||
|
['username', '执行者'],
|
||||||
|
['action_ip', '执行IP', 'callback', function($value){
|
||||||
|
return long2ip(intval($value));
|
||||||
|
}],
|
||||||
|
['module_title', '所属模块'],
|
||||||
|
['create_time', '执行时间', 'datetime', '', 'Y-m-d H:i:s'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addOrder(['title' => 'admin_action', 'username' => 'admin_user', 'module_title' => 'admin_module.title'])
|
||||||
|
->addFilter(['admin_action.title', 'admin_user.username', 'module_title' => 'admin_module.title'])
|
||||||
|
->addRightButton('edit', ['icon' => 'fa fa-eye', 'title' => '详情', 'href' => url('details', ['id' => '__id__'])])
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->setPages($page) // 设置分页数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志详情
|
||||||
|
* @param null $id 日志id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function details($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
$info = LogModel::getAll(['admin_log.id' => $id]);
|
||||||
|
$info = $info[0];
|
||||||
|
$info['action_ip'] = long2ip(intval($info['action_ip']));
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('编辑') // 设置页面标题
|
||||||
|
->addFormItems([ // 批量添加表单项
|
||||||
|
['hidden', 'id'],
|
||||||
|
['static', 'title', '行为名称'],
|
||||||
|
['static', 'username', '执行者'],
|
||||||
|
['static', 'record_id', '目标ID'],
|
||||||
|
['static', 'action_ip', '执行IP'],
|
||||||
|
['static', 'module_title', '所属模块'],
|
||||||
|
['textarea', 'remark', '备注'],
|
||||||
|
])
|
||||||
|
->hideBtn('submit')
|
||||||
|
->setFormData($info) // 设置表单数据
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
}
|
537
application/admin/controller/Menu.php
Normal file
537
application/admin/controller/Menu.php
Normal file
@ -0,0 +1,537 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Module as ModuleModel;
|
||||||
|
use app\admin\model\Menu as MenuModel;
|
||||||
|
use app\user\model\Role as RoleModel;
|
||||||
|
use think\facade\Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点管理
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Menu extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 节点首页
|
||||||
|
* @param string $group 分组
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function index($group = 'admin')
|
||||||
|
{
|
||||||
|
// 保存模块排序
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$modules = $this->request->post('sort/a');
|
||||||
|
if ($modules) {
|
||||||
|
$data = [];
|
||||||
|
foreach ($modules as $key => $module) {
|
||||||
|
$data[] = [
|
||||||
|
'id' => $module,
|
||||||
|
'sort' => $key + 1
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$MenuModel = new MenuModel();
|
||||||
|
if (false !== $MenuModel->saveAll($data)) {
|
||||||
|
$this->success('保存成功');
|
||||||
|
} else {
|
||||||
|
$this->error('保存失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cookie('__forward__', $_SERVER['REQUEST_URI']);
|
||||||
|
// 配置分组信息
|
||||||
|
$list_group = MenuModel::getGroup();
|
||||||
|
foreach ($list_group as $key => $value) {
|
||||||
|
$tab_list[$key]['title'] = $value;
|
||||||
|
$tab_list[$key]['url'] = url('index', ['group' => $key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模块排序
|
||||||
|
if ($group == 'module-sort') {
|
||||||
|
$map['status'] = 1;
|
||||||
|
$map['pid'] = 0;
|
||||||
|
$modules = MenuModel::where($map)->order('sort,id')->column('icon,title', 'id');
|
||||||
|
$this->assign('modules', $modules);
|
||||||
|
} else {
|
||||||
|
// 获取节点数据
|
||||||
|
$data_list = MenuModel::getMenusByGroup($group);
|
||||||
|
|
||||||
|
$max_level = $this->request->get('max', 0);
|
||||||
|
|
||||||
|
$this->assign('menus', $this->getNestMenu($data_list, $max_level));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assign('tab_nav', ['tab_list' => $tab_list, 'curr_tab' => $group]);
|
||||||
|
$this->assign('page_title', '节点管理');
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增节点
|
||||||
|
* @param string $module 所属模块
|
||||||
|
* @param string $pid 所属节点id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function add($module = 'admin', $pid = '')
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post('', null, 'trim');
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Menu');
|
||||||
|
// 验证失败 输出错误信息
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
// 顶部节点url检查
|
||||||
|
if ($data['pid'] == 0 && $data['url_value'] == '' && ($data['url_type'] == 'module_admin' || $data['url_type'] == 'module_home')) {
|
||||||
|
$this->error('顶级节点的节点链接不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($menu = MenuModel::create($data)) {
|
||||||
|
// 自动创建子节点
|
||||||
|
if ($data['auto_create'] == 1 && !empty($data['child_node'])) {
|
||||||
|
unset($data['icon']);
|
||||||
|
unset($data['params']);
|
||||||
|
$this->createChildNode($data, $menu['id']);
|
||||||
|
}
|
||||||
|
// 添加角色权限
|
||||||
|
if (isset($data['role'])) {
|
||||||
|
$this->setRoleMenu($menu['id'], $data['role']);
|
||||||
|
}
|
||||||
|
Cache::clear();
|
||||||
|
// 记录行为
|
||||||
|
$details = '所属模块('.$data['module'].'),所属节点ID('.$data['pid'].'),节点标题('.$data['title'].'),节点链接('.$data['url_value'].')';
|
||||||
|
action_log('menu_add', 'admin_menu', $menu['id'], UID, $details);
|
||||||
|
$this->success('新增成功', cookie('__forward__'));
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('新增节点')
|
||||||
|
->addLinkage('module', '所属模块', '', ModuleModel::getModule(), $module, url('ajax/getModuleMenus'), 'pid')
|
||||||
|
->addFormItems([
|
||||||
|
['select', 'pid', '所属节点', '所属上级节点', MenuModel::getMenuTree(0, '', $module), $pid],
|
||||||
|
['text', 'title', '节点标题'],
|
||||||
|
['radio', 'url_type', '链接类型', '', ['module_admin' => '模块链接(后台)', 'module_home' => '模块链接(前台)', 'link' => '普通链接'], 'module_admin']
|
||||||
|
])
|
||||||
|
->addFormItem(
|
||||||
|
'text',
|
||||||
|
'url_value',
|
||||||
|
'节点链接',
|
||||||
|
"可留空,如果是模块链接,请填写<code>模块/控制器/操作</code>,如:<code>admin/menu/add</code>。如果是普通链接,则直接填写url地址,如:<code>http://www.dolphinphp.com</code>"
|
||||||
|
)
|
||||||
|
->addText('params', '参数', '如:a=1&b=2')
|
||||||
|
->addSelect('role', '角色', '除超级管理员外,拥有该节点权限的角色', RoleModel::where('id', 'neq', 1)->column('id,name'), '', 'multiple')
|
||||||
|
->addRadio('auto_create', '自动添加子节点', '选择【是】则自动添加指定的子节点', ['否', '是'], 0)
|
||||||
|
->addCheckbox('child_node', '子节点', '仅上面选项为【是】时起作用', ['add' => '新增', 'edit' => '编辑', 'delete' => '删除', 'enable' => '启用', 'disable' => '禁用', 'quickedit' => '快速编辑'], 'add,edit,delete,enable,disable,quickedit')
|
||||||
|
->addRadio('url_target', '打开方式', '', ['_self' => '当前窗口', '_blank' => '新窗口'], '_self')
|
||||||
|
->addIcon('icon', '图标', '导航图标')
|
||||||
|
->addRadio('online_hide', '网站上线后隐藏', '关闭开发模式后,则隐藏该菜单节点', ['否', '是'], 0)
|
||||||
|
->addText('sort', '排序', '', 100)
|
||||||
|
->setTrigger('auto_create', '1', 'child_node', false)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑节点
|
||||||
|
* @param int $id 节点ID
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function edit($id = 0)
|
||||||
|
{
|
||||||
|
if ($id === 0) $this->error('缺少参数');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post('', null, 'trim');
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Menu');
|
||||||
|
// 验证失败 输出错误信息
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
// 顶部节点url检查
|
||||||
|
if ($data['pid'] == 0 && $data['url_value'] == '' && ($data['url_type'] == 'module_admin' || $data['url_type'] == 'module_home')) {
|
||||||
|
$this->error('顶级节点的节点链接不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置角色权限
|
||||||
|
$this->setRoleMenu($data['id'], isset($data['role']) ? $data['role'] : []);
|
||||||
|
|
||||||
|
// 验证是否更改所属模块,如果是,则该节点的所有子孙节点的模块都要修改
|
||||||
|
$map['id'] = $data['id'];
|
||||||
|
$map['module'] = $data['module'];
|
||||||
|
if (!MenuModel::where($map)->find()) {
|
||||||
|
MenuModel::changeModule($data['id'], $data['module']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MenuModel::update($data)) {
|
||||||
|
Cache::clear();
|
||||||
|
// 记录行为
|
||||||
|
$details = '节点ID('.$id.')';
|
||||||
|
action_log('menu_edit', 'admin_menu', $id, UID, $details);
|
||||||
|
$this->success('编辑成功', cookie('__forward__'));
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$info = MenuModel::get($id);
|
||||||
|
// 拥有该节点权限的角色
|
||||||
|
$info['role'] = RoleModel::getRoleWithMenu($id);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('编辑节点')
|
||||||
|
->addFormItem('hidden', 'id')
|
||||||
|
->addLinkage('module', '所属模块', '', ModuleModel::getModule(), '', url('ajax/getModuleMenus'), 'pid')
|
||||||
|
->addFormItem('select', 'pid', '所属节点', '所属上级节点', MenuModel::getMenuTree(0, '', $info['module']))
|
||||||
|
->addFormItem('text', 'title', '节点标题')
|
||||||
|
->addFormItem('radio', 'url_type', '链接类型', '', ['module_admin' => '模块链接(后台)', 'module_home' => '模块链接(前台)', 'link' => '普通链接'], 'module_admin')
|
||||||
|
->addFormItem(
|
||||||
|
'text',
|
||||||
|
'url_value',
|
||||||
|
'节点链接',
|
||||||
|
"可留空,如果是模块链接,请填写<code>模块/控制器/操作</code>,如:<code>admin/menu/add</code>。如果是普通链接,则直接填写url地址,如:<code>http://www.dolphinphp.com</code>"
|
||||||
|
)
|
||||||
|
->addText('params', '参数', '如:a=1&b=2')
|
||||||
|
->addSelect('role', '角色', '除超级管理员外,拥有该节点权限的角色', RoleModel::where('id', 'neq', 1)->column('id,name'), '', 'multiple')
|
||||||
|
->addRadio('url_target', '打开方式', '', ['_self' => '当前窗口', '_blank' => '新窗口'], '_self')
|
||||||
|
->addIcon('icon', '图标', '导航图标')
|
||||||
|
->addRadio('online_hide', '网站上线后隐藏', '关闭开发模式后,则隐藏该菜单节点', ['否', '是'])
|
||||||
|
->addText('sort', '排序', '', 100)
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置角色权限
|
||||||
|
* @param string $role_id 角色id
|
||||||
|
* @param array $roles 角色id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
private function setRoleMenu($role_id = '', $roles = [])
|
||||||
|
{
|
||||||
|
$RoleModel = new RoleModel();
|
||||||
|
|
||||||
|
// 该节点的所有子节点,包括本身节点
|
||||||
|
$menu_child = MenuModel::getChildsId($role_id);
|
||||||
|
$menu_child[] = (int)$role_id;
|
||||||
|
// 该节点的所有上下级节点
|
||||||
|
$menu_all = MenuModel::getLinkIds($role_id);
|
||||||
|
$menu_all = array_map('strval', $menu_all);
|
||||||
|
|
||||||
|
if (!empty($roles)) {
|
||||||
|
// 拥有该节点的所有角色id及节点权限
|
||||||
|
$role_menu_auth = RoleModel::getRoleWithMenu($role_id, true);
|
||||||
|
// 已有该节点权限的角色id
|
||||||
|
$role_exists = array_keys($role_menu_auth);
|
||||||
|
// 新节点权限的角色
|
||||||
|
$role_new = $roles;
|
||||||
|
// 原有权限角色差集
|
||||||
|
$role_diff = array_diff($role_exists, $role_new);
|
||||||
|
// 新权限角色差集
|
||||||
|
$role_diff_new = array_diff($role_new, $role_exists);
|
||||||
|
// 新节点角色权限
|
||||||
|
$role_new_auth = RoleModel::getAuthWithRole($roles);
|
||||||
|
|
||||||
|
// 删除原先角色的该节点权限
|
||||||
|
if ($role_diff) {
|
||||||
|
$role_del_auth = [];
|
||||||
|
foreach ($role_diff as $role) {
|
||||||
|
$auth = json_decode($role_menu_auth[$role], true);
|
||||||
|
$auth_new = array_diff($auth, $menu_child);
|
||||||
|
$role_del_auth[] = [
|
||||||
|
'id' => $role,
|
||||||
|
'menu_auth' => array_values($auth_new)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if ($role_del_auth) {
|
||||||
|
$RoleModel->saveAll($role_del_auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增权限角色
|
||||||
|
if ($role_diff_new) {
|
||||||
|
$role_update_auth = [];
|
||||||
|
foreach ($role_new_auth as $role => $auth) {
|
||||||
|
$auth = json_decode($auth, true);
|
||||||
|
if (in_array($role, $role_diff_new)) {
|
||||||
|
$auth = array_unique(array_merge($auth, $menu_all));
|
||||||
|
}
|
||||||
|
$role_update_auth[] = [
|
||||||
|
'id' => $role,
|
||||||
|
'menu_auth' => array_values($auth)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if ($role_update_auth) {
|
||||||
|
$RoleModel->saveAll($role_update_auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$role_menu_auth = RoleModel::getRoleWithMenu($role_id, true);
|
||||||
|
$role_del_auth = [];
|
||||||
|
foreach ($role_menu_auth as $role => $auth) {
|
||||||
|
$auth = json_decode($auth, true);
|
||||||
|
$auth_new = array_diff($auth, $menu_child);
|
||||||
|
$role_del_auth[] = [
|
||||||
|
'id' => $role,
|
||||||
|
'menu_auth' => array_values($auth_new)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if ($role_del_auth) {
|
||||||
|
$RoleModel->saveAll($role_del_auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除节点
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
$id = $this->request->param('id');
|
||||||
|
$menu = MenuModel::where('id', $id)->find();
|
||||||
|
|
||||||
|
if ($menu['system_menu'] == '1') $this->error('系统节点,禁止删除');
|
||||||
|
|
||||||
|
// 获取该节点的所有后辈节点id
|
||||||
|
$menu_childs = MenuModel::getChildsId($id);
|
||||||
|
|
||||||
|
// 要删除的所有节点id
|
||||||
|
$all_ids = array_merge([(int)$id], $menu_childs);
|
||||||
|
|
||||||
|
// 删除节点
|
||||||
|
if (MenuModel::destroy($all_ids)) {
|
||||||
|
Cache::clear();
|
||||||
|
// 记录行为
|
||||||
|
$details = '节点ID('.$id.'),节点标题('.$menu['title'].'),节点链接('.$menu['url_value'].')';
|
||||||
|
action_log('menu_delete', 'admin_menu', $id, UID, $details);
|
||||||
|
$this->success('删除成功');
|
||||||
|
} else {
|
||||||
|
$this->error('删除失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存节点排序
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
if (!empty($data)) {
|
||||||
|
$menus = $this->parseMenu($data['menus']);
|
||||||
|
foreach ($menus as $menu) {
|
||||||
|
if ($menu['pid'] == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MenuModel::update($menu);
|
||||||
|
}
|
||||||
|
Cache::clear();
|
||||||
|
$this->success('保存成功');
|
||||||
|
} else {
|
||||||
|
$this->error('没有需要保存的节点');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->error('非法请求');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加子节点
|
||||||
|
* @param array $data 节点数据
|
||||||
|
* @param string $pid 父节点id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function createChildNode($data = [], $pid = '')
|
||||||
|
{
|
||||||
|
$url_value = substr($data['url_value'], 0, strrpos($data['url_value'], '/')).'/';
|
||||||
|
$child_node = [];
|
||||||
|
$data['pid'] = $pid;
|
||||||
|
|
||||||
|
foreach ($data['child_node'] as $item) {
|
||||||
|
switch ($item) {
|
||||||
|
case 'add':
|
||||||
|
$data['title'] = '新增';
|
||||||
|
break;
|
||||||
|
case 'edit':
|
||||||
|
$data['title'] = '编辑';
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
$data['title'] = '删除';
|
||||||
|
break;
|
||||||
|
case 'enable':
|
||||||
|
$data['title'] = '启用';
|
||||||
|
break;
|
||||||
|
case 'disable':
|
||||||
|
$data['title'] = '禁用';
|
||||||
|
break;
|
||||||
|
case 'quickedit':
|
||||||
|
$data['title'] = '快速编辑';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$data['url_value'] = $url_value.$item;
|
||||||
|
$data['create_time'] = $this->request->time();
|
||||||
|
$data['update_time'] = $this->request->time();
|
||||||
|
$child_node[] = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($child_node) {
|
||||||
|
$MenuModel = new MenuModel();
|
||||||
|
$MenuModel->insertAll($child_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归解析节点
|
||||||
|
* @param array $menus 节点数据
|
||||||
|
* @param int $pid 上级节点id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array 解析成可以写入数据库的格式
|
||||||
|
*/
|
||||||
|
private function parseMenu($menus = [], $pid = 0)
|
||||||
|
{
|
||||||
|
$sort = 1;
|
||||||
|
$result = [];
|
||||||
|
foreach ($menus as $menu) {
|
||||||
|
$result[] = [
|
||||||
|
'id' => (int)$menu['id'],
|
||||||
|
'pid' => (int)$pid,
|
||||||
|
'sort' => $sort,
|
||||||
|
];
|
||||||
|
if (isset($menu['children'])) {
|
||||||
|
$result = array_merge($result, $this->parseMenu($menu['children'], $menu['id']));
|
||||||
|
}
|
||||||
|
$sort ++;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取嵌套式节点
|
||||||
|
* @param array $lists 原始节点数组
|
||||||
|
* @param int $pid 父级id
|
||||||
|
* @param int $max_level 最多返回多少层,0为不限制
|
||||||
|
* @param int $curr_level 当前层数
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getNestMenu($lists = [], $max_level = 0, $pid = 0, $curr_level = 1)
|
||||||
|
{
|
||||||
|
$result = '';
|
||||||
|
foreach ($lists as $key => $value) {
|
||||||
|
if ($value['pid'] == $pid) {
|
||||||
|
$disable = $value['status'] == 0 ? 'dd-disable' : '';
|
||||||
|
|
||||||
|
// 组合节点
|
||||||
|
$result .= '<li class="dd-item dd3-item '.$disable.'" data-id="'.$value['id'].'">';
|
||||||
|
$result .= '<div class="dd-handle dd3-handle">拖拽</div><div class="dd3-content"><i class="'.$value['icon'].'"></i> '.$value['title'];
|
||||||
|
if ($value['url_value'] != '') {
|
||||||
|
$result .= '<span class="link"><i class="fa fa-link"></i> '.$value['url_value'].'</span>';
|
||||||
|
}
|
||||||
|
$result .= '<div class="action">';
|
||||||
|
$result .= '<a href="'.url('add', ['module' => $value['module'], 'pid' => $value['id']]).'" data-toggle="tooltip" data-original-title="新增子节点"><i class="list-icon fa fa-plus fa-fw"></i></a><a href="'.url('edit', ['id' => $value['id']]).'" data-toggle="tooltip" data-original-title="编辑"><i class="list-icon fa fa-pencil fa-fw"></i></a>';
|
||||||
|
if ($value['status'] == 0) {
|
||||||
|
// 启用
|
||||||
|
$result .= '<a href="javascript:void(0);" data-ids="'.$value['id'].'" class="enable" data-toggle="tooltip" data-original-title="启用"><i class="list-icon fa fa-check-circle-o fa-fw"></i></a>';
|
||||||
|
} else {
|
||||||
|
// 禁用
|
||||||
|
$result .= '<a href="javascript:void(0);" data-ids="'.$value['id'].'" class="disable" data-toggle="tooltip" data-original-title="禁用"><i class="list-icon fa fa-ban fa-fw"></i></a>';
|
||||||
|
}
|
||||||
|
$result .= '<a href="'.url('delete', ['id' => $value['id'], 'table' => 'admin_menu']).'" data-toggle="tooltip" data-original-title="删除" class="ajax-get confirm"><i class="list-icon fa fa-times fa-fw"></i></a></div>';
|
||||||
|
$result .= '</div>';
|
||||||
|
|
||||||
|
if ($max_level == 0 || $curr_level != $max_level) {
|
||||||
|
unset($lists[$key]);
|
||||||
|
// 下级节点
|
||||||
|
$children = $this->getNestMenu($lists, $max_level, $value['id'], $curr_level + 1);
|
||||||
|
if ($children != '') {
|
||||||
|
$result .= '<ol class="dd-list">'.$children.'</ol>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result .= '</li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用节点
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
$id = input('param.ids');
|
||||||
|
$menu = MenuModel::where('id', $id)->find();
|
||||||
|
$details = '节点ID('.$id.'),节点标题('.$menu['title'].'),节点链接('.$menu['url_value'].')';
|
||||||
|
$this->setStatus('enable', ['menu_enable', 'admin_menu', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用节点
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
$id = input('param.ids');
|
||||||
|
$menu = MenuModel::where('id', $id)->find();
|
||||||
|
$details = '节点ID('.$id.'),节点标题('.$menu['title'].'),节点链接('.$menu['url_value'].')';
|
||||||
|
$this->setStatus('disable', ['menu_disable', 'admin_menu', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置状态
|
||||||
|
* @param string $type 类型
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 小乌 <82950492@qq.com>
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$id = input('param.ids');
|
||||||
|
|
||||||
|
$status = $type == 'enable' ? 1 : 0;
|
||||||
|
|
||||||
|
if (false !== MenuModel::where('id', $id)->setField('status', $status)) {
|
||||||
|
Cache::clear();
|
||||||
|
// 记录行为日志
|
||||||
|
if (!empty($record)) {
|
||||||
|
call_user_func_array('action_log', $record);
|
||||||
|
}
|
||||||
|
$this->success('操作成功');
|
||||||
|
} else {
|
||||||
|
$this->error('操作失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
70
application/admin/controller/Message.php
Normal file
70
application/admin/controller/Message.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\user\model\Message as MessageModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Message extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 消息中心
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$data_list = MessageModel::where($this->getMap())
|
||||||
|
->where('uid_receive', UID)
|
||||||
|
->order($this->getOrder('id DESC'))
|
||||||
|
->paginate();
|
||||||
|
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setTableName('admin_message')
|
||||||
|
->addTopButton('enable', ['title' => '设置已阅读'])
|
||||||
|
->addTopButton('delete')
|
||||||
|
->addRightButton('enable', ['title' => '设置已阅读'])
|
||||||
|
->addRightButton('delete')
|
||||||
|
->addColumns([
|
||||||
|
['uid_send', '发送者', 'callback', 'get_nickname'],
|
||||||
|
['type', '分类'],
|
||||||
|
['content', '内容'],
|
||||||
|
['status', '状态', 'status', '', ['未读', '已读']],
|
||||||
|
['create_time', '发送时间', 'datetime'],
|
||||||
|
['read_time', '阅读时间', 'datetime'],
|
||||||
|
['right_button', '操作', 'btn'],
|
||||||
|
])
|
||||||
|
->addFilter('type')
|
||||||
|
->addFilter('status', ['未读', '已读'])
|
||||||
|
->setRowList($data_list)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置已阅读
|
||||||
|
* @param array $ids
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($ids = [])
|
||||||
|
{
|
||||||
|
empty($ids) && $this->error('参数错误');
|
||||||
|
$map = [
|
||||||
|
['uid_receive', '=', UID],
|
||||||
|
['id', 'in', $ids]
|
||||||
|
];
|
||||||
|
$result = MessageModel::where($map)
|
||||||
|
->update(['status' => 1, 'read_time' => $this->request->time()]);
|
||||||
|
if (false !== $result) {
|
||||||
|
$this->success('设置成功');
|
||||||
|
} else {
|
||||||
|
$this->error('设置失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
607
application/admin/controller/Module.php
Normal file
607
application/admin/controller/Module.php
Normal file
@ -0,0 +1,607 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\model\Module as ModuleModel;
|
||||||
|
use app\admin\model\Plugin as PluginModel;
|
||||||
|
use app\admin\model\Menu as MenuModel;
|
||||||
|
use app\admin\model\Action as ActionModel;
|
||||||
|
use think\facade\Cache;
|
||||||
|
use util\Database;
|
||||||
|
use util\Sql;
|
||||||
|
use util\File;
|
||||||
|
use util\PHPZip;
|
||||||
|
use util\Tree;
|
||||||
|
use think\Db;
|
||||||
|
use think\facade\Hook;
|
||||||
|
use think\facade\Env;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模块管理控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Module extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 模块首页
|
||||||
|
* @param string $group 分组
|
||||||
|
* @param string $type 显示类型
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function index($group = 'local', $type = '')
|
||||||
|
{
|
||||||
|
// 配置分组信息
|
||||||
|
$list_group = ['local' => '本地模块'];
|
||||||
|
$tab_list = [];
|
||||||
|
foreach ($list_group as $key => $value) {
|
||||||
|
$tab_list[$key]['title'] = $value;
|
||||||
|
$tab_list[$key]['url'] = url('index', ['group' => $key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听tab钩子
|
||||||
|
Hook::listen('module_index_tab_list', $tab_list);
|
||||||
|
|
||||||
|
switch ($group) {
|
||||||
|
case 'local':
|
||||||
|
// 查询条件
|
||||||
|
$keyword = $this->request->get('keyword', '');
|
||||||
|
|
||||||
|
if (input('?param.status') && input('param.status') != '_all') {
|
||||||
|
$status = input('param.status');
|
||||||
|
} else {
|
||||||
|
$status = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$ModuleModel = new ModuleModel();
|
||||||
|
$result = $ModuleModel->getAll($keyword, $status);
|
||||||
|
|
||||||
|
if ($result['modules'] === false) {
|
||||||
|
$this->error($ModuleModel->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
$type_show = Cache::get('module_type_show');
|
||||||
|
$type_show = $type != '' ? $type : ($type_show == false ? 'block' : $type_show);
|
||||||
|
Cache::set('module_type_show', $type_show);
|
||||||
|
$type = $type_show == 'block' ? 'list' : 'block';
|
||||||
|
|
||||||
|
$this->assign('page_title', '模块管理');
|
||||||
|
$this->assign('modules', $result['modules']);
|
||||||
|
$this->assign('total', $result['total']);
|
||||||
|
$this->assign('tab_nav', ['tab_list' => $tab_list, 'curr_tab' => $group]);
|
||||||
|
$this->assign('type', $type);
|
||||||
|
return $this->fetch();
|
||||||
|
break;
|
||||||
|
case 'online':
|
||||||
|
return '<h2>正在建设中...</h2>';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->error('非法操作');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安装模块
|
||||||
|
* @param string $name 模块标识
|
||||||
|
* @param int $confirm 是否确认
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function install($name = '', $confirm = 0)
|
||||||
|
{
|
||||||
|
// 设置最大执行时间和内存大小
|
||||||
|
ini_set('max_execution_time', '0');
|
||||||
|
ini_set('memory_limit', '1024M');
|
||||||
|
|
||||||
|
if ($name == '') $this->error('模块不存在!');
|
||||||
|
if ($name == 'admin' || $name == 'user') $this->error('禁止操作系统核心模块!');
|
||||||
|
|
||||||
|
// 模块配置信息
|
||||||
|
$module_info = ModuleModel::getInfoFromFile($name);
|
||||||
|
|
||||||
|
if ($confirm == 0) {
|
||||||
|
$need_module = [];
|
||||||
|
$need_plugin = [];
|
||||||
|
$table_check = [];
|
||||||
|
// 检查模块依赖
|
||||||
|
if (isset($module_info['need_module']) && !empty($module_info['need_module'])) {
|
||||||
|
$need_module = $this->checkDependence('module', $module_info['need_module']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查插件依赖
|
||||||
|
if (isset($module_info['need_plugin']) && !empty($module_info['need_plugin'])) {
|
||||||
|
$need_plugin = $this->checkDependence('plugin', $module_info['need_plugin']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据表
|
||||||
|
if (isset($module_info['tables']) && !empty($module_info['tables'])) {
|
||||||
|
foreach ($module_info['tables'] as $table) {
|
||||||
|
if (Db::query("SHOW TABLES LIKE '".config('database.prefix')."{$table}'")) {
|
||||||
|
$table_check[] = [
|
||||||
|
'table' => config('database.prefix')."{$table}",
|
||||||
|
'result' => '<span class="text-danger">存在同名</span>'
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$table_check[] = [
|
||||||
|
'table' => config('database.prefix')."{$table}",
|
||||||
|
'result' => '<i class="fa fa-check text-success"></i>'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assign('need_module', $need_module);
|
||||||
|
$this->assign('need_plugin', $need_plugin);
|
||||||
|
$this->assign('table_check', $table_check);
|
||||||
|
$this->assign('name', $name);
|
||||||
|
$this->assign('page_title', '安装模块:'. $name);
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行安装文件
|
||||||
|
$install_file = realpath(Env::get('app_path').$name.'/install.php');
|
||||||
|
if (file_exists($install_file)) {
|
||||||
|
@include($install_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行安装模块sql文件
|
||||||
|
$sql_file = realpath(Env::get('app_path').$name.'/sql/install.sql');
|
||||||
|
if (file_exists($sql_file)) {
|
||||||
|
if (isset($module_info['database_prefix']) && !empty($module_info['database_prefix'])) {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file, false, [$module_info['database_prefix'] => config('database.prefix')]);
|
||||||
|
} else {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file);
|
||||||
|
}
|
||||||
|
if (!empty($sql_statement)) {
|
||||||
|
foreach ($sql_statement as $value) {
|
||||||
|
try{
|
||||||
|
Db::execute($value);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
$this->error('导入SQL失败,请检查install.sql的语句是否正确');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加菜单
|
||||||
|
$menus = ModuleModel::getMenusFromFile($name);
|
||||||
|
if (is_array($menus) && !empty($menus)) {
|
||||||
|
if (false === $this->addMenus($menus, $name)) {
|
||||||
|
$this->error('菜单添加失败,请重新安装');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有模块设置信息
|
||||||
|
if (isset($module_info['config']) && !empty($module_info['config'])) {
|
||||||
|
$module_info['config'] = json_encode(parse_config($module_info['config']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有模块授权配置
|
||||||
|
if (isset($module_info['access']) && !empty($module_info['access'])) {
|
||||||
|
$module_info['access'] = json_encode($module_info['access']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有行为规则
|
||||||
|
if (isset($module_info['action']) && !empty($module_info['action'])) {
|
||||||
|
$ActionModel = new ActionModel;
|
||||||
|
if (!$ActionModel->saveAll($module_info['action'])) {
|
||||||
|
MenuModel::where('module', $name)->delete();
|
||||||
|
$this->error('行为添加失败,请重新安装');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将模块信息写入数据库
|
||||||
|
$ModuleModel = new ModuleModel($module_info);
|
||||||
|
$allowField = ['name','title','icon','description','author','author_url','config','access','version','identifier','status'];
|
||||||
|
|
||||||
|
if ($ModuleModel->allowField($allowField)->save()) {
|
||||||
|
// 复制静态资源目录
|
||||||
|
File::copy_dir(Env::get('app_path'). $name. '/public', Env::get('root_path'). 'public');
|
||||||
|
// 删除静态资源目录
|
||||||
|
File::del_dir(Env::get('app_path'). $name. '/public');
|
||||||
|
cache('modules', null);
|
||||||
|
cache('module_all', null);
|
||||||
|
// 记录行为
|
||||||
|
action_log('module_install', 'admin_module', 0, UID, $module_info['title']);
|
||||||
|
$this->success('模块安装成功', 'index');
|
||||||
|
} else {
|
||||||
|
MenuModel::where('module', $name)->delete();
|
||||||
|
$this->error('模块安装失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卸载模块
|
||||||
|
* @param string $name 模块名
|
||||||
|
* @param int $confirm 是否确认
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function uninstall($name = '', $confirm = 0)
|
||||||
|
{
|
||||||
|
if ($name == '') $this->error('模块不存在!');
|
||||||
|
if ($name == 'admin') $this->error('禁止操作系统模块!');
|
||||||
|
|
||||||
|
// 模块配置信息
|
||||||
|
$module_info = ModuleModel::getInfoFromFile($name);
|
||||||
|
|
||||||
|
if ($confirm == 0) {
|
||||||
|
$this->assign('name', $name);
|
||||||
|
$this->assign('page_title', '卸载模块:'. $name);
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行卸载文件
|
||||||
|
$uninstall_file = realpath(Env::get('app_path').$name.'/uninstall.php');
|
||||||
|
if (file_exists($uninstall_file)) {
|
||||||
|
@include($uninstall_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行卸载模块sql文件
|
||||||
|
$clear = $this->request->get('clear');
|
||||||
|
if ($clear == 1) {
|
||||||
|
$sql_file = realpath(Env::get('app_path').$name.'/sql/uninstall.sql');
|
||||||
|
if (file_exists($sql_file)) {
|
||||||
|
if (isset($module_info['database_prefix']) && !empty($module_info['database_prefix'])) {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file, false, [$module_info['database_prefix'] => config('database.prefix')]);
|
||||||
|
} else {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($sql_statement)) {
|
||||||
|
foreach ($sql_statement as $sql) {
|
||||||
|
try{
|
||||||
|
Db::execute($sql);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
$this->error('卸载失败,请检查uninstall.sql的语句是否正确');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除菜单
|
||||||
|
if (false === MenuModel::where('module', $name)->delete()) {
|
||||||
|
$this->error('菜单删除失败,请重新卸载');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除授权信息
|
||||||
|
if (false === Db::name('admin_access')->where('module', $name)->delete()) {
|
||||||
|
$this->error('删除授权信息失败,请重新卸载');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除行为规则
|
||||||
|
if (false === Db::name('admin_action')->where('module', $name)->delete()) {
|
||||||
|
$this->error('删除行为信息失败,请重新卸载');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除模块信息
|
||||||
|
if (ModuleModel::where('name', $name)->delete()) {
|
||||||
|
// 复制静态资源目录
|
||||||
|
File::copy_dir(Env::get('root_path'). 'public/static/'. $name, Env::get('app_path').$name.'/public/static/'. $name);
|
||||||
|
// 删除静态资源目录
|
||||||
|
File::del_dir(Env::get('root_path'). 'public/static/'. $name);
|
||||||
|
cache('modules', null);
|
||||||
|
cache('module_all', null);
|
||||||
|
// 记录行为
|
||||||
|
action_log('module_uninstall', 'admin_module', 0, UID, $module_info['title']);
|
||||||
|
$this->success('模块卸载成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('模块卸载失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新模块配置
|
||||||
|
* @param string $name 模块名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function update($name = '')
|
||||||
|
{
|
||||||
|
$name == '' && $this->error('缺少模块名!');
|
||||||
|
|
||||||
|
$Module = ModuleModel::get(['name' => $name]);
|
||||||
|
!$Module && $this->error('模块不存在,或未安装');
|
||||||
|
|
||||||
|
// 模块配置信息
|
||||||
|
$module_info = ModuleModel::getInfoFromFile($name);
|
||||||
|
unset($module_info['name']);
|
||||||
|
|
||||||
|
// 检查是否有模块设置信息
|
||||||
|
if (isset($module_info['config']) && !empty($module_info['config'])) {
|
||||||
|
$module_info['config'] = json_encode(parse_config($module_info['config']));
|
||||||
|
} else {
|
||||||
|
$module_info['config'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有模块授权配置
|
||||||
|
if (isset($module_info['access']) && !empty($module_info['access'])) {
|
||||||
|
$module_info['access'] = json_encode($module_info['access']);
|
||||||
|
} else {
|
||||||
|
$module_info['access'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新模块信息
|
||||||
|
if (false !== $Module->save($module_info)) {
|
||||||
|
$this->success('模块配置更新成功');
|
||||||
|
} else {
|
||||||
|
$this->error('模块配置更新失败,请重试');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出模块
|
||||||
|
* @param string $name 模块名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function export($name = '')
|
||||||
|
{
|
||||||
|
if ($name == '') $this->error('缺少模块名');
|
||||||
|
|
||||||
|
$export_data = $this->request->get('export_data', '');
|
||||||
|
if ($export_data == '') {
|
||||||
|
$this->assign('page_title', '导出模块:'. $name);
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模块导出目录
|
||||||
|
$module_dir = Env::get('root_path'). 'export/module/'. $name;
|
||||||
|
|
||||||
|
// 删除旧的导出数据
|
||||||
|
if (is_dir($module_dir)) {
|
||||||
|
File::del_dir($module_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制模块目录到导出目录
|
||||||
|
File::copy_dir(Env::get('app_path'). $name, $module_dir);
|
||||||
|
// 复制静态资源目录
|
||||||
|
File::copy_dir(Env::get('root_path'). 'public/static/'. $name, $module_dir.'/public/static/'. $name);
|
||||||
|
|
||||||
|
// 模块本地配置信息
|
||||||
|
$module_info = ModuleModel::getInfoFromFile($name);
|
||||||
|
|
||||||
|
// 检查是否有模块设置信息
|
||||||
|
if (isset($module_info['config'])) {
|
||||||
|
$db_config = ModuleModel::where('name', $name)->value('config');
|
||||||
|
$db_config = json_decode($db_config, true);
|
||||||
|
// 获取最新的模块设置信息
|
||||||
|
$module_info['config'] = set_config_value($module_info['config'], $db_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有模块行为信息
|
||||||
|
$action = Db::name('admin_action')->where('module', $name)->field('module,name,title,remark,rule,log,status')->select();
|
||||||
|
if ($action) {
|
||||||
|
$module_info['action'] = $action;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表前缀
|
||||||
|
$module_info['database_prefix'] = config('database.prefix');
|
||||||
|
|
||||||
|
// 生成配置文件
|
||||||
|
if (false === $this->buildInfoFile($module_info, $name)) {
|
||||||
|
$this->error('模块配置文件创建失败,请重新导出');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取模型菜单并导出
|
||||||
|
$fields = 'id,pid,title,icon,url_type,url_value,url_target,online_hide,sort,status';
|
||||||
|
$menus = MenuModel::getMenusByGroup($name, $fields);
|
||||||
|
if (false === $this->buildMenuFile($menus, $name)) {
|
||||||
|
$this->error('模型菜单文件创建失败,请重新导出');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出数据库表
|
||||||
|
if (isset($module_info['tables']) && !empty($module_info['tables'])) {
|
||||||
|
if (!is_dir($module_dir. '/sql')) {
|
||||||
|
mkdir($module_dir. '/sql', 644, true);
|
||||||
|
}
|
||||||
|
if (!Database::export($module_info['tables'], $module_dir. '/sql/install.sql', config('database.prefix'), $export_data)) {
|
||||||
|
$this->error('数据库文件创建失败,请重新导出');
|
||||||
|
}
|
||||||
|
if (!Database::exportUninstall($module_info['tables'], $module_dir. '/sql/uninstall.sql', config('database.prefix'))) {
|
||||||
|
$this->error('数据库文件创建失败,请重新导出');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录行为
|
||||||
|
action_log('module_export', 'admin_module', 0, UID, $module_info['title']);
|
||||||
|
|
||||||
|
// 打包下载
|
||||||
|
$archive = new PHPZip;
|
||||||
|
return $archive->ZipAndDownload($module_dir, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建模块菜单文件
|
||||||
|
* @param array $menus 菜单
|
||||||
|
* @param string $name 模块名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function buildMenuFile($menus = [], $name = '')
|
||||||
|
{
|
||||||
|
$menus = Tree::toLayer($menus);
|
||||||
|
|
||||||
|
// 美化数组格式
|
||||||
|
$menus = var_export($menus, true);
|
||||||
|
$menus = preg_replace("/(\d+|'id'|'pid') =>(.*)/", '', $menus);
|
||||||
|
$menus = preg_replace("/'child' => (.*)(\r\n|\r|\n)\s*array/", "'child' => $1array", $menus);
|
||||||
|
$menus = str_replace(['array (', ')'], ['[', ']'], $menus);
|
||||||
|
$menus = preg_replace("/(\s*?\r?\n\s*?)+/", "\n", $menus);
|
||||||
|
|
||||||
|
$content = <<<INFO
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* 菜单信息
|
||||||
|
*/
|
||||||
|
return {$menus};
|
||||||
|
|
||||||
|
INFO;
|
||||||
|
// 写入到文件
|
||||||
|
return file_put_contents(Env::get('root_path'). 'export/module/'. $name. '/menus.php', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建模块配置文件
|
||||||
|
* @param array $info 模块配置信息
|
||||||
|
* @param string $name 模块名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function buildInfoFile($info = [], $name = '')
|
||||||
|
{
|
||||||
|
// 美化数组格式
|
||||||
|
$info = var_export($info, true);
|
||||||
|
$info = preg_replace("/'(.*)' => (.*)(\r\n|\r|\n)\s*array/", "'$1' => array", $info);
|
||||||
|
$info = preg_replace("/(\d+) => (\s*)(\r\n|\r|\n)\s*array/", "array", $info);
|
||||||
|
$info = preg_replace("/(\d+ => )/", "", $info);
|
||||||
|
$info = preg_replace("/array \((\r\n|\r|\n)\s*\)/", "[)", $info);
|
||||||
|
$info = preg_replace("/array \(/", "[", $info);
|
||||||
|
$info = preg_replace("/\)/", "]", $info);
|
||||||
|
|
||||||
|
$content = <<<INFO
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* 模块信息
|
||||||
|
*/
|
||||||
|
return {$info};
|
||||||
|
|
||||||
|
INFO;
|
||||||
|
// 写入到文件
|
||||||
|
return file_put_contents(Env::get('root_path'). 'export/module/'. $name. '/info.php', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置状态
|
||||||
|
* @param string $type 类型:disable/enable
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = input('param.ids');
|
||||||
|
empty($ids) && $this->error('缺少主键');
|
||||||
|
|
||||||
|
$module = ModuleModel::where('id', $ids)->find();
|
||||||
|
$module['system_module'] == 1 && $this->error('禁止操作系统内置模块');
|
||||||
|
|
||||||
|
$status = $type == 'enable' ? 1 : 0;
|
||||||
|
|
||||||
|
// 将模块对应的菜单禁用或启用
|
||||||
|
$map = [
|
||||||
|
'pid' => 0,
|
||||||
|
'module' => $module['name']
|
||||||
|
];
|
||||||
|
MenuModel::where($map)->setField('status', $status);
|
||||||
|
|
||||||
|
if (false !== ModuleModel::where('id', $ids)->setField('status', $status)) {
|
||||||
|
// 记录日志
|
||||||
|
call_user_func_array('action_log', ['module_'.$type, 'admin_module', 0, UID, $module['title']]);
|
||||||
|
$this->success('操作成功');
|
||||||
|
} else {
|
||||||
|
$this->error('操作失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用模块
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
$this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用模块
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
$this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加模型菜单
|
||||||
|
* @param array $menus 菜单
|
||||||
|
* @param string $module 模型名称
|
||||||
|
* @param int $pid 父级ID
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function addMenus($menus = [], $module = '', $pid = 0)
|
||||||
|
{
|
||||||
|
foreach ($menus as $menu) {
|
||||||
|
$data = [
|
||||||
|
'pid' => $pid,
|
||||||
|
'module' => $module,
|
||||||
|
'title' => $menu['title'],
|
||||||
|
'icon' => isset($menu['icon']) ? $menu['icon'] : 'fa fa-fw fa-puzzle-piece',
|
||||||
|
'url_type' => isset($menu['url_type']) ? $menu['url_type'] : 'module_admin',
|
||||||
|
'url_value' => isset($menu['url_value']) ? $menu['url_value'] : '',
|
||||||
|
'url_target' => isset($menu['url_target']) ? $menu['url_target'] : '_self',
|
||||||
|
'online_hide' => isset($menu['online_hide']) ? $menu['online_hide'] : 0,
|
||||||
|
'status' => isset($menu['status']) ? $menu['status'] : 1
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = MenuModel::create($data);
|
||||||
|
if (!$result) return false;
|
||||||
|
|
||||||
|
if (isset($menu['child'])) {
|
||||||
|
$this->addMenus($menu['child'], $module, $result['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查依赖
|
||||||
|
* @param string $type 类型:module/plugin
|
||||||
|
* @param array $data 检查数据
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function checkDependence($type = '', $data = [])
|
||||||
|
{
|
||||||
|
$need = [];
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if (!isset($value[3])) {
|
||||||
|
$value[3] = '=';
|
||||||
|
}
|
||||||
|
// 当前版本
|
||||||
|
if ($type == 'module') {
|
||||||
|
$curr_version = ModuleModel::where('identifier', $value[1])->value('version');
|
||||||
|
} else {
|
||||||
|
$curr_version = PluginModel::where('identifier', $value[1])->value('version');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 比对版本
|
||||||
|
$result = version_compare($curr_version, $value[2], $value[3]);
|
||||||
|
$need[$key] = [
|
||||||
|
$type => $value[0],
|
||||||
|
'identifier' => $value[1],
|
||||||
|
'version' => $curr_version ? $curr_version : '未安装',
|
||||||
|
'version_need' => $value[3].$value[2],
|
||||||
|
'result' => $result ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $need;
|
||||||
|
}
|
||||||
|
}
|
146
application/admin/controller/Packet.php
Normal file
146
application/admin/controller/Packet.php
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Packet as PacketModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据包控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Packet extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 首页
|
||||||
|
* @param string $group 分组
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed|string
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function index($group = 'local')
|
||||||
|
{
|
||||||
|
// 配置分组信息
|
||||||
|
$list_group = ['local' => '本地数据包'];
|
||||||
|
$tab_list = [];
|
||||||
|
foreach ($list_group as $key => $value) {
|
||||||
|
$tab_list[$key]['title'] = $value;
|
||||||
|
$tab_list[$key]['url'] = url('index', ['group' => $key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$PacketModel = new PacketModel;
|
||||||
|
$data_list = $PacketModel->getAll();
|
||||||
|
foreach ($data_list as &$value) {
|
||||||
|
if (isset($value['author_url']) && !empty($value['author_url'])) {
|
||||||
|
$value['author'] = '<a href="'. $value['author_url']. '" target="_blank">'. $value['author'] .'</a>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data_list === false) {
|
||||||
|
$this->error($PacketModel->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义按钮
|
||||||
|
$btn_install = [
|
||||||
|
'title' => '安装',
|
||||||
|
'icon' => 'fa fa-fw fa-sign-in',
|
||||||
|
'class' => 'btn btn-xs btn-default ajax-get confirm',
|
||||||
|
'href' => url('install', ['name' => '__id__'])
|
||||||
|
];
|
||||||
|
$btn_uninstall = [
|
||||||
|
'title' => '卸载',
|
||||||
|
'icon' => 'fa fa-fw fa-sign-out',
|
||||||
|
'class' => 'btn btn-xs btn-default ajax-get confirm',
|
||||||
|
'href' => url('uninstall', ['name' => '__id__'])
|
||||||
|
];
|
||||||
|
$btn_install_all = [
|
||||||
|
'title' => '安装',
|
||||||
|
'icon' => 'fa fa-fw fa-sign-in',
|
||||||
|
'class' => 'btn btn-primary ajax-post confirm',
|
||||||
|
'href' => url('install')
|
||||||
|
];
|
||||||
|
$btn_uninstall_all = [
|
||||||
|
'title' => '卸载',
|
||||||
|
'icon' => 'fa fa-fw fa-sign-out',
|
||||||
|
'class' => 'btn btn-danger ajax-post confirm',
|
||||||
|
'href' => url('uninstall')
|
||||||
|
];
|
||||||
|
|
||||||
|
switch ($group) {
|
||||||
|
case 'local':
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setPageTitle('数据包管理') // 设置页面标题
|
||||||
|
->setPrimaryKey('name')
|
||||||
|
->setTabNav($tab_list, $group) // 设置tab分页
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['name', '名称'],
|
||||||
|
['title', '标题'],
|
||||||
|
['author', '作者'],
|
||||||
|
['version', '版本号'],
|
||||||
|
['status', '是否安装', 'yesno'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButton('custom', $btn_install_all)
|
||||||
|
->addTopButton('custom', $btn_uninstall_all)
|
||||||
|
->addRightButton('custom', $btn_install) // 添加右侧按钮
|
||||||
|
->addRightButton('custom', $btn_uninstall) // 添加右侧按钮
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
break;
|
||||||
|
case 'online':
|
||||||
|
return '<h2>正在制作中...</h2>';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安装
|
||||||
|
* @param string $name 数据包名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function install($name = '')
|
||||||
|
{
|
||||||
|
$names = $name != '' ? (array)$name : $this->request->param('ids/a');
|
||||||
|
|
||||||
|
foreach ($names as $name) {
|
||||||
|
$result = PacketModel::install($name);
|
||||||
|
if ($result === true) {
|
||||||
|
if (!PacketModel::where('name', $name)->find()) {
|
||||||
|
$data = PacketModel::getInfoFromFile($name);
|
||||||
|
$data['status'] = 1;
|
||||||
|
$data['tables'] = json_encode($data['tables']);
|
||||||
|
PacketModel::create($data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error('安装失败:'. $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 记录行为
|
||||||
|
$packet_titles = PacketModel::where('name', 'in', $names)->column('title');
|
||||||
|
action_log('packet_install', 'admin_packet', 0, UID, implode('、', $packet_titles));
|
||||||
|
$this->success('安装成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卸载
|
||||||
|
* @param string $name 数据包名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function uninstall($name = '')
|
||||||
|
{
|
||||||
|
$names = $name != '' ? (array)$name : $this->request->param('ids/a');
|
||||||
|
|
||||||
|
// 记录行为
|
||||||
|
$packet_titles = PacketModel::where('name', 'in', $names)->column('title');
|
||||||
|
action_log('packet_uninstall', 'admin_packet', 0, UID, implode('、', $packet_titles));
|
||||||
|
|
||||||
|
foreach ($names as $name) {
|
||||||
|
PacketModel::uninstall($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->success('卸载成功');
|
||||||
|
}
|
||||||
|
}
|
612
application/admin/controller/Plugin.php
Normal file
612
application/admin/controller/Plugin.php
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Plugin as PluginModel;
|
||||||
|
use app\admin\model\HookPlugin as HookPluginModel;
|
||||||
|
use think\facade\Cache;
|
||||||
|
use util\Sql;
|
||||||
|
use think\Db;
|
||||||
|
use think\facade\Hook;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件管理控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class Plugin extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 首页
|
||||||
|
* @param string $group 分组
|
||||||
|
* @param string $type 显示类型
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function index($group = 'local', $type = '')
|
||||||
|
{
|
||||||
|
// 配置分组信息
|
||||||
|
$list_group = ['local' => '本地插件'];
|
||||||
|
$tab_list = [];
|
||||||
|
foreach ($list_group as $key => $value) {
|
||||||
|
$tab_list[$key]['title'] = $value;
|
||||||
|
$tab_list[$key]['url'] = url('index', ['group' => $key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听tab钩子
|
||||||
|
Hook::listen('plugin_index_tab_list', $tab_list);
|
||||||
|
|
||||||
|
switch ($group) {
|
||||||
|
case 'local':
|
||||||
|
// 查询条件
|
||||||
|
$keyword = $this->request->get('keyword', '');
|
||||||
|
|
||||||
|
if (input('?param.status') && input('param.status') != '_all') {
|
||||||
|
$status = input('param.status');
|
||||||
|
} else {
|
||||||
|
$status = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$PluginModel = new PluginModel;
|
||||||
|
$result = $PluginModel->getAll($keyword, $status);
|
||||||
|
|
||||||
|
if ($result['plugins'] === false) {
|
||||||
|
$this->error($PluginModel->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
$type_show = Cache::get('plugin_type_show');
|
||||||
|
$type_show = $type != '' ? $type : ($type_show == false ? 'block' : $type_show);
|
||||||
|
Cache::set('plugin_type_show', $type_show);
|
||||||
|
$type = $type_show == 'block' ? 'list' : 'block';
|
||||||
|
|
||||||
|
$this->assign('page_title', '插件管理');
|
||||||
|
$this->assign('plugins', $result['plugins']);
|
||||||
|
$this->assign('total', $result['total']);
|
||||||
|
$this->assign('tab_nav', ['tab_list' => $tab_list, 'curr_tab' => $group]);
|
||||||
|
$this->assign('type', $type);
|
||||||
|
return $this->fetch();
|
||||||
|
break;
|
||||||
|
case 'online':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安装插件
|
||||||
|
* @param string $name 插件标识
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function install($name = '')
|
||||||
|
{
|
||||||
|
// 设置最大执行时间和内存大小
|
||||||
|
ini_set('max_execution_time', '0');
|
||||||
|
ini_set('memory_limit', '1024M');
|
||||||
|
|
||||||
|
$plug_name = trim($name);
|
||||||
|
if ($plug_name == '') $this->error('插件不存在!');
|
||||||
|
|
||||||
|
$plugin_class = get_plugin_class($plug_name);
|
||||||
|
|
||||||
|
if (!class_exists($plugin_class)) {
|
||||||
|
$this->error('插件不存在!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化插件
|
||||||
|
$plugin = new $plugin_class;
|
||||||
|
// 插件预安装
|
||||||
|
if(!$plugin->install()) {
|
||||||
|
$this->error('插件预安装失败!原因:'. $plugin->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加钩子
|
||||||
|
if (isset($plugin->hooks) && !empty($plugin->hooks)) {
|
||||||
|
if (!HookPluginModel::addHooks($plugin->hooks, $name)) {
|
||||||
|
$this->error('安装插件钩子时出现错误,请重新安装');
|
||||||
|
}
|
||||||
|
cache('hook_plugins', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行安装插件sql文件
|
||||||
|
$sql_file = realpath(config('plugin_path').$name.'/install.sql');
|
||||||
|
if (file_exists($sql_file)) {
|
||||||
|
if (isset($plugin->database_prefix) && $plugin->database_prefix != '') {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file, false, [$plugin->database_prefix => config('database.prefix')]);
|
||||||
|
} else {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($sql_statement)) {
|
||||||
|
foreach ($sql_statement as $value) {
|
||||||
|
Db::execute($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插件配置信息
|
||||||
|
$plugin_info = $plugin->info;
|
||||||
|
|
||||||
|
// 验证插件信息
|
||||||
|
$result = $this->validate($plugin_info, 'Plugin');
|
||||||
|
// 验证失败 输出错误信息
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
// 并入插件配置值
|
||||||
|
$plugin_info['config'] = $plugin->getConfigValue();
|
||||||
|
|
||||||
|
// 将插件信息写入数据库
|
||||||
|
if (PluginModel::create($plugin_info)) {
|
||||||
|
cache('plugin_all', null);
|
||||||
|
$this->success('插件安装成功');
|
||||||
|
} else {
|
||||||
|
$this->error('插件安装失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卸载插件
|
||||||
|
* @param string $name 插件标识
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function uninstall($name = '')
|
||||||
|
{
|
||||||
|
$plug_name = trim($name);
|
||||||
|
if ($plug_name == '') $this->error('插件不存在!');
|
||||||
|
|
||||||
|
$class = get_plugin_class($plug_name);
|
||||||
|
if (!class_exists($class)) {
|
||||||
|
$this->error('插件不存在!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化插件
|
||||||
|
$plugin = new $class;
|
||||||
|
// 插件预卸
|
||||||
|
if(!$plugin->uninstall()) {
|
||||||
|
$this->error('插件预卸载失败!原因:'. $plugin->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 卸载插件自带钩子
|
||||||
|
if (isset($plugin->hooks) && !empty($plugin->hooks)) {
|
||||||
|
if (false === HookPluginModel::deleteHooks($plug_name)) {
|
||||||
|
$this->error('卸载插件钩子时出现错误,请重新卸载');
|
||||||
|
}
|
||||||
|
cache('hook_plugins', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行卸载插件sql文件
|
||||||
|
$sql_file = realpath(config('plugin_path').$plug_name.'/uninstall.sql');
|
||||||
|
if (file_exists($sql_file)) {
|
||||||
|
if (isset($plugin->database_prefix) && $plugin->database_prefix != '') {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file, true, [$plugin->database_prefix => config('database.prefix')]);
|
||||||
|
} else {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($sql_statement)) {
|
||||||
|
Db::execute($sql_statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除插件信息
|
||||||
|
if (PluginModel::where('name', $plug_name)->delete()) {
|
||||||
|
cache('plugin_all', null);
|
||||||
|
$this->success('插件卸载成功');
|
||||||
|
} else {
|
||||||
|
$this->error('插件卸载失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件管理
|
||||||
|
* @param string $name 插件名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function manage($name = '')
|
||||||
|
{
|
||||||
|
cookie('__forward__', $_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
|
// 加载自定义后台页面
|
||||||
|
if (plugin_action_exists($name, 'Admin', 'index')) {
|
||||||
|
return plugin_action($name, 'Admin', 'index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载系统的后台页面
|
||||||
|
$class = get_plugin_class($name);
|
||||||
|
if (!class_exists($class)) {
|
||||||
|
$this->error($name.'插件不存在!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化插件
|
||||||
|
$plugin = new $class;
|
||||||
|
|
||||||
|
// 获取后台字段信息,并分析
|
||||||
|
if (isset($plugin->admin)) {
|
||||||
|
$admin = $this->parseAdmin($plugin->admin);
|
||||||
|
} else {
|
||||||
|
$admin = $this->parseAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!plugin_model_exists($name)) {
|
||||||
|
$this->error('插件: '.$name.' 缺少模型文件!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取插件模型实例
|
||||||
|
$PluginModel = get_plugin_model($name);
|
||||||
|
$order = $this->getOrder();
|
||||||
|
$map = $this->getMap();
|
||||||
|
$data_list = $PluginModel->where($map)->order($order)->paginate();
|
||||||
|
$page = $data_list->render();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
$builder = ZBuilder::make('table')
|
||||||
|
->setPageTitle($admin['title']) // 设置页面标题
|
||||||
|
->setPluginName($name)
|
||||||
|
->setTableName($admin['table_name'])
|
||||||
|
->setSearch($admin['search_field'], $admin['search_title']) // 设置搜索框
|
||||||
|
->addOrder($admin['order'])
|
||||||
|
->addTopButton('back', [
|
||||||
|
'title' => '返回插件列表',
|
||||||
|
'icon' => 'fa fa-reply',
|
||||||
|
'href' => url('index')
|
||||||
|
])
|
||||||
|
->addTopButtons($admin['top_buttons']) // 批量添加顶部按钮
|
||||||
|
->addRightButtons($admin['right_buttons']); // 批量添加右侧按钮
|
||||||
|
|
||||||
|
// 自定义顶部按钮
|
||||||
|
if (!empty($admin['custom_top_buttons'])) {
|
||||||
|
foreach ($admin['custom_top_buttons'] as $custom) {
|
||||||
|
$builder->addTopButton('custom', $custom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 自定义右侧按钮
|
||||||
|
if (!empty($admin['custom_right_buttons'])) {
|
||||||
|
foreach ($admin['custom_right_buttons'] as $custom) {
|
||||||
|
$builder->addRightButton('custom', $custom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表头筛选
|
||||||
|
if (is_array($admin['filter'])) {
|
||||||
|
foreach ($admin['filter'] as $column => $params) {
|
||||||
|
$options = isset($params[0]) ? $params[0] : [];
|
||||||
|
$default = isset($params[1]) ? $params[1] : [];
|
||||||
|
$type = isset($params[2]) ? $params[2] : 'checkbox';
|
||||||
|
$builder->addFilter($column, $options, $default, $type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$builder->addFilter($admin['filter']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $builder
|
||||||
|
->addColumns($admin['columns']) // 批量添加数据列
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->setPages($page) // 设置分页数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件新增方法
|
||||||
|
* @param string $plugin_name 插件名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add($plugin_name = '')
|
||||||
|
{
|
||||||
|
// 如果存在自定义的新增方法,则优先执行
|
||||||
|
if (plugin_action_exists($plugin_name, 'Admin', 'add')) {
|
||||||
|
$params = $this->request->param();
|
||||||
|
return plugin_action($plugin_name, 'Admin', 'add', $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 执行插件的验证器(如果存在的话)
|
||||||
|
if (plugin_validate_exists($plugin_name)) {
|
||||||
|
$plugin_validate = get_plugin_validate($plugin_name);
|
||||||
|
if (!$plugin_validate->check($data)) {
|
||||||
|
// 验证失败 输出错误信息
|
||||||
|
$this->error($plugin_validate->getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化模型并添加数据
|
||||||
|
$PluginModel = get_plugin_model($plugin_name);
|
||||||
|
if ($PluginModel->data($data)->save()) {
|
||||||
|
$this->success('新增成功', cookie('__forward__'));
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取插件模型
|
||||||
|
$class = get_plugin_class($plugin_name);
|
||||||
|
if (!class_exists($class)) {
|
||||||
|
$this->error('插件不存在!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化插件
|
||||||
|
$plugin = new $class;
|
||||||
|
if (!isset($plugin->fields)) {
|
||||||
|
$this->error('插件新增、编辑字段不存在!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('新增')
|
||||||
|
->addFormItems($plugin->fields)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑插件方法
|
||||||
|
* @param string $id 数据id
|
||||||
|
* @param string $plugin_name 插件名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = '', $plugin_name = '')
|
||||||
|
{
|
||||||
|
// 如果存在自定义的编辑方法,则优先执行
|
||||||
|
if (plugin_action_exists($plugin_name, 'Admin', 'edit')) {
|
||||||
|
$params = $this->request->param();
|
||||||
|
return plugin_action($plugin_name, 'Admin', 'edit', $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 执行插件的验证器(如果存在的话)
|
||||||
|
if (plugin_validate_exists($plugin_name)) {
|
||||||
|
$plugin_validate = get_plugin_validate($plugin_name);
|
||||||
|
if (!$plugin_validate->check($data)) {
|
||||||
|
// 验证失败 输出错误信息
|
||||||
|
$this->error($plugin_validate->getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化模型并添加数据
|
||||||
|
$PluginModel = get_plugin_model($plugin_name);
|
||||||
|
if (false !== $PluginModel->isUpdate(true)->save($data)) {
|
||||||
|
$this->success('编辑成功', cookie('__forward__'));
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取插件类名
|
||||||
|
$class = get_plugin_class($plugin_name);
|
||||||
|
if (!class_exists($class)) {
|
||||||
|
$this->error('插件不存在!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化插件
|
||||||
|
$plugin = new $class;
|
||||||
|
if (!isset($plugin->fields)) {
|
||||||
|
$this->error('插件新增、编辑字段不存在!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$PluginModel = get_plugin_model($plugin_name);
|
||||||
|
$info = $PluginModel->find($id);
|
||||||
|
if (!$info) {
|
||||||
|
$this->error('找不到数据!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('编辑')
|
||||||
|
->addHidden('id')
|
||||||
|
->addFormItems($plugin->fields)
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件参数设置
|
||||||
|
* @param string $name 插件名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function config($name = '')
|
||||||
|
{
|
||||||
|
// 更新配置
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
$data = json_encode($data);
|
||||||
|
|
||||||
|
if (false !== PluginModel::where('name', $name)->update(['config' => $data])) {
|
||||||
|
$this->success('更新成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('更新失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$plugin_class = get_plugin_class($name);
|
||||||
|
// 实例化插件
|
||||||
|
$plugin = new $plugin_class;
|
||||||
|
$trigger = isset($plugin->trigger) ? $plugin->trigger : [];
|
||||||
|
|
||||||
|
// 插件配置值
|
||||||
|
$info = PluginModel::where('name', $name)->field('id,name,config')->find();
|
||||||
|
$db_config = json_decode($info['config'], true);
|
||||||
|
|
||||||
|
// 插件配置项
|
||||||
|
$config = include config('plugin_path'). $name. '/config.php';
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('插件设置')
|
||||||
|
->addFormItems($config)
|
||||||
|
->setFormData($db_config)
|
||||||
|
->setTrigger($trigger)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置状态
|
||||||
|
* @param string $type 状态类型:enable/disable
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$_t = input('param._t', '');
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
empty($ids) && $this->error('缺少主键');
|
||||||
|
|
||||||
|
$status = $type == 'enable' ? 1 : 0;
|
||||||
|
|
||||||
|
if ($_t != '') {
|
||||||
|
parent::setStatus($type, $record);
|
||||||
|
} else {
|
||||||
|
$plugins = PluginModel::where('id', 'in', $ids)->value('name');
|
||||||
|
if ($plugins) {
|
||||||
|
HookPluginModel::$type($plugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false !== PluginModel::where('id', 'in', $ids)->setField('status', $status)) {
|
||||||
|
$this->success('操作成功');
|
||||||
|
} else {
|
||||||
|
$this->error('操作失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用插件/禁用插件数据
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
$this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用插件/启用插件数据
|
||||||
|
* @param array $record 行为日志内容
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
$this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除插件数据
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
$this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行插件内部方法
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
$plugin = input('param._plugin');
|
||||||
|
$controller = input('param._controller');
|
||||||
|
$action = input('param._action');
|
||||||
|
$params = $this->request->except(['_plugin', '_controller', '_action'], 'param');
|
||||||
|
|
||||||
|
if (empty($plugin) || empty($controller) || empty($action)) {
|
||||||
|
$this->error('没有指定插件名称、控制器名称或操作名称');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!plugin_action_exists($plugin, $controller, $action)) {
|
||||||
|
$this->error("找不到方法:{$plugin}/{$controller}/{$action}");
|
||||||
|
}
|
||||||
|
return plugin_action($plugin, $controller, $action, $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分析后台字段信息
|
||||||
|
* @param array $data 字段信息
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function parseAdmin($data = [])
|
||||||
|
{
|
||||||
|
$admin = [
|
||||||
|
'title' => '数据列表',
|
||||||
|
'search_title' => '',
|
||||||
|
'search_field' => [],
|
||||||
|
'order' => '',
|
||||||
|
'filter' => '',
|
||||||
|
'table_name' => '',
|
||||||
|
'columns' => [],
|
||||||
|
'right_buttons' => [],
|
||||||
|
'top_buttons' => [],
|
||||||
|
'customs' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
if (empty($data)) {
|
||||||
|
return $admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理工具栏按钮链接
|
||||||
|
if (isset($data['top_buttons']) && !empty($data['top_buttons'])) {
|
||||||
|
$this->parseButton('top_buttons', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理右侧按钮链接
|
||||||
|
if (isset($data['right_buttons']) && !empty($data['right_buttons'])) {
|
||||||
|
$this->parseButton('right_buttons', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_merge($admin, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析按钮链接
|
||||||
|
* @param string $button 按钮名称
|
||||||
|
* @param array $data 字段信息
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function parseButton($button, &$data)
|
||||||
|
{
|
||||||
|
foreach ($data[$button] as $key => &$value) {
|
||||||
|
// 处理自定义按钮
|
||||||
|
if ($key === 'customs') {
|
||||||
|
if (!empty($value)) {
|
||||||
|
foreach ($value as &$custom) {
|
||||||
|
if (isset($custom['href']['url']) && $custom['href']['url'] != '') {
|
||||||
|
$params = isset($custom['href']['params']) ? $custom['href']['params'] : [];
|
||||||
|
$custom['href'] = plugin_url($custom['href']['url'], $params);
|
||||||
|
$data['custom_'.$button][] = $custom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($data[$button][$key]);
|
||||||
|
}
|
||||||
|
if (!is_numeric($key) && isset($value['href']['url']) && $value['href']['url'] != '') {
|
||||||
|
$value['href'] = plugin_url($value['href']['url']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
178
application/admin/controller/System.php
Normal file
178
application/admin/controller/System.php
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\admin\model\Config as ConfigModel;
|
||||||
|
use app\admin\model\Module as ModuleModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统模块控制器
|
||||||
|
* @package app\admin\controller
|
||||||
|
*/
|
||||||
|
class System extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 系统设置
|
||||||
|
* @param string $group 分组
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function index($group = 'base')
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
if (isset(config('config_group')[$group])) {
|
||||||
|
// 查询该分组下所有的配置项名和类型
|
||||||
|
$items = ConfigModel::where('group', $group)->where('status', 1)->column('name,type');
|
||||||
|
|
||||||
|
foreach ($items as $name => $type) {
|
||||||
|
if (!isset($data[$name])) {
|
||||||
|
switch ($type) {
|
||||||
|
// 开关
|
||||||
|
case 'switch':
|
||||||
|
$data[$name] = 0;
|
||||||
|
break;
|
||||||
|
case 'checkbox':
|
||||||
|
$data[$name] = '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果值是数组则转换成字符串,适用于复选框等类型
|
||||||
|
if (is_array($data[$name])) {
|
||||||
|
$data[$name] = implode(',', $data[$name]);
|
||||||
|
}
|
||||||
|
switch ($type) {
|
||||||
|
// 开关
|
||||||
|
case 'switch':
|
||||||
|
$data[$name] = 1;
|
||||||
|
break;
|
||||||
|
// 日期时间
|
||||||
|
case 'date':
|
||||||
|
case 'time':
|
||||||
|
case 'datetime':
|
||||||
|
$data[$name] = strtotime($data[$name]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigModel::where('name', $name)->update(['value' => $data[$name]]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 保存模块配置
|
||||||
|
if (false === ModuleModel::where('name', $group)->update(['config' => json_encode($data)])) {
|
||||||
|
$this->error('更新失败');
|
||||||
|
}
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('module_config_'.$group, $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache('system_config', null);
|
||||||
|
// 记录行为
|
||||||
|
action_log('system_config_update', 'admin_config', 0, UID, "分组($group)");
|
||||||
|
$this->success('更新成功', url('index', ['group' => $group]));
|
||||||
|
} else {
|
||||||
|
// 配置分组信息
|
||||||
|
$list_group = config('config_group');
|
||||||
|
|
||||||
|
// 读取模型配置
|
||||||
|
$modules = ModuleModel::where('config', 'neq', '')
|
||||||
|
->where('status', 1)
|
||||||
|
->column('config,title,name', 'name');
|
||||||
|
foreach ($modules as $name => $module) {
|
||||||
|
$list_group[$name] = $module['title'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$tab_list = [];
|
||||||
|
foreach ($list_group as $key => $value) {
|
||||||
|
$tab_list[$key]['title'] = $value;
|
||||||
|
$tab_list[$key]['url'] = url('index', ['group' => $key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset(config('config_group')[$group])) {
|
||||||
|
// 查询条件
|
||||||
|
$map['group'] = $group;
|
||||||
|
$map['status'] = 1;
|
||||||
|
|
||||||
|
// 数据列表
|
||||||
|
$data_list = ConfigModel::where($map)
|
||||||
|
->order('sort asc,id asc')
|
||||||
|
->field('group', true)
|
||||||
|
->select();
|
||||||
|
$data_list = $data_list->toArray();
|
||||||
|
|
||||||
|
foreach ($data_list as &$value) {
|
||||||
|
// 解析options
|
||||||
|
if ($value['options'] != '') {
|
||||||
|
$value['options'] = parse_attr($value['options']);
|
||||||
|
}
|
||||||
|
// 默认模块列表
|
||||||
|
if ($value['name'] == 'home_default_module') {
|
||||||
|
$value['options'] = array_merge(['index' => '默认'], ModuleModel::getModule());
|
||||||
|
}
|
||||||
|
switch ($value['type']) {
|
||||||
|
// 日期时间
|
||||||
|
case 'date':
|
||||||
|
$value['value'] = $value['value'] != '' ? date('Y-m-d', $value['value']) : '';
|
||||||
|
break;
|
||||||
|
case 'time':
|
||||||
|
$value['value'] = $value['value'] != '' ? date('H:i:s', $value['value']) : '';
|
||||||
|
break;
|
||||||
|
case 'datetime':
|
||||||
|
$value['value'] = $value['value'] != '' ? date('Y-m-d H:i:s', $value['value']) : '';
|
||||||
|
break;
|
||||||
|
case 'linkages':
|
||||||
|
$value['token'] = $this->createLinkagesToken($value['table'], $value['option'], $value['key']);
|
||||||
|
break;
|
||||||
|
case 'colorpicker':
|
||||||
|
$value['mode'] = 'rgba';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('系统设置')
|
||||||
|
->setTabNav($tab_list, $group)
|
||||||
|
->setFormItems($data_list)
|
||||||
|
->fetch();
|
||||||
|
} else {
|
||||||
|
// 模块配置
|
||||||
|
$module_info = ModuleModel::getInfoFromFile($group);
|
||||||
|
$config = $module_info['config'];
|
||||||
|
$trigger = isset($module_info['trigger']) ? $module_info['trigger'] : [];
|
||||||
|
|
||||||
|
// 数据库内的模块信息
|
||||||
|
$db_config = ModuleModel::where('name', $group)->value('config');
|
||||||
|
$db_config = json_decode($db_config, true);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTitle('模块设置')
|
||||||
|
->setTabNav($tab_list, $group)
|
||||||
|
->addFormItems($config)
|
||||||
|
->setFormdata($db_config) // 设置表格数据
|
||||||
|
->setTrigger($trigger) // 设置触发
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建快速多级联动Token
|
||||||
|
* @param string $table 表名
|
||||||
|
* @param string $option
|
||||||
|
* @param string $key
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
private function createLinkagesToken($table = '', $option = '', $key = '')
|
||||||
|
{
|
||||||
|
$table_token = substr(sha1($table.'-'.$option.'-'.$key.'-'.session('user_auth.last_login_ip').'-'.UID.'-'.session('user_auth.last_login_time')), 0, 8);
|
||||||
|
session($table_token, ['table' => $table, 'option' => $option, 'key' => $key]);
|
||||||
|
return $table_token;
|
||||||
|
}
|
||||||
|
}
|
75
application/admin/model/Access.php
Normal file
75
application/admin/model/Access.php
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\facade\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一授权模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Access extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_access';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户授权节点
|
||||||
|
* @param int $uid 用户id
|
||||||
|
* @param string $group 权限分组,可以以点分开模型名称和分组名称,如user.group
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
public function getAuthNode($uid = 0, $group = '')
|
||||||
|
{
|
||||||
|
if ($uid == 0 || $group == '') {
|
||||||
|
$this->error = '缺少参数';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strpos($group, '.')) {
|
||||||
|
list($module, $group) = explode('.', $group);
|
||||||
|
} else {
|
||||||
|
$module = Request::module();
|
||||||
|
}
|
||||||
|
|
||||||
|
$map = [
|
||||||
|
'module' => $module,
|
||||||
|
'group' => $group,
|
||||||
|
'uid' => $uid
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->where($map)->column('nid');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查用户的某个节点是否授权
|
||||||
|
* @param int $uid 用户id
|
||||||
|
* @param string $group $group 权限分组,可以以点分开模型名称和分组名称,如user.group
|
||||||
|
* @param int $node 需要检查的节点id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function checkAuthNode($uid = 0, $group = '', $node = 0)
|
||||||
|
{
|
||||||
|
if ($uid == 0 || $group == '' || $node == 0) {
|
||||||
|
$this->error = '缺少参数';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取该用户的所有授权节点
|
||||||
|
$nodes = $this->getAuthNode($uid, $group);
|
||||||
|
if (!$nodes) {
|
||||||
|
$this->error = '该用户没有授权任何节点';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nodes = array_flip($nodes);
|
||||||
|
if (isset($nodes[$node])) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
$this->error = '未授权';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
application/admin/model/Action.php
Normal file
17
application/admin/model/Action.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Action extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_action';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
}
|
87
application/admin/model/Attachment.php
Normal file
87
application/admin/model/Attachment.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附件模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Attachment extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_attachment';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据附件id获取路径
|
||||||
|
* @param string|array $id 附件id
|
||||||
|
* @param int $type 类型:0-补全目录,1-直接返回数据库记录的地址
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|bool|mixed|string
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function getFilePath($id = '', $type = 0)
|
||||||
|
{
|
||||||
|
if (is_array($id)) {
|
||||||
|
$data_list = $this->where('id', 'in', $id)->select();
|
||||||
|
$paths = [];
|
||||||
|
foreach ($data_list as $key => $value) {
|
||||||
|
if ($value['driver'] == 'local') {
|
||||||
|
$paths[$value['id']] = ($type == 0 ? PUBLIC_PATH : '').$value['path'];
|
||||||
|
} else {
|
||||||
|
$paths[$value['id']] = $value['path'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $paths;
|
||||||
|
} else {
|
||||||
|
$data = $this->where('id', $id)->find();
|
||||||
|
if ($data) {
|
||||||
|
if ($data['driver'] == 'local') {
|
||||||
|
return ($type == 0 ? PUBLIC_PATH : '').$data['path'];
|
||||||
|
} else {
|
||||||
|
return $data['path'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据图片id获取缩略图路径,如果缩略图不存在,则返回原图路径
|
||||||
|
* @param string $id 图片id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed|string|Model|null
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function getThumbPath($id = '')
|
||||||
|
{
|
||||||
|
$result = $this->where('id', $id)->field('path,driver,thumb')->find();
|
||||||
|
if ($result) {
|
||||||
|
if ($result['driver'] == 'local') {
|
||||||
|
return $result['thumb'] != '' ? PUBLIC_PATH.$result['thumb'] : PUBLIC_PATH.$result['path'];
|
||||||
|
} else {
|
||||||
|
return $result['thumb'] != '' ? $result['thumb'] : $result['path'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据附件id获取名称
|
||||||
|
* @param string $id 附件id
|
||||||
|
* @return string 名称
|
||||||
|
*/
|
||||||
|
public function getFileName($id = '')
|
||||||
|
{
|
||||||
|
return $this->where('id', $id)->value('name');
|
||||||
|
}
|
||||||
|
}
|
48
application/admin/model/Config.php
Normal file
48
application/admin/model/Config.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台配置模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Config extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_config';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置信息
|
||||||
|
* @param string $name 配置名
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getConfig($name = '')
|
||||||
|
{
|
||||||
|
$configs = self::column('value,type', 'name');
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($configs as $config) {
|
||||||
|
switch ($config['type']) {
|
||||||
|
case 'array':
|
||||||
|
$result[$config['name']] = parse_attr($config['value']);
|
||||||
|
break;
|
||||||
|
case 'checkbox':
|
||||||
|
if ($config['value'] != '') {
|
||||||
|
$result[$config['name']] = explode(',', $config['value']);
|
||||||
|
} else {
|
||||||
|
$result[$config['name']] = [];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result[$config['name']] = $config['value'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name != '' ? $result[$name] : $result;
|
||||||
|
}
|
||||||
|
}
|
72
application/admin/model/Hook.php
Normal file
72
application/admin/model/Hook.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钩子模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Hook extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_hook';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加钩子
|
||||||
|
* @param array $hooks 钩子
|
||||||
|
* @param string $plugin_name
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public static function addHooks($hooks = [], $plugin_name = '')
|
||||||
|
{
|
||||||
|
if (!empty($hooks) && is_array($hooks)) {
|
||||||
|
$data = [];
|
||||||
|
foreach ($hooks as $name => $description) {
|
||||||
|
if (is_numeric($name)) {
|
||||||
|
$name = $description;
|
||||||
|
$description = '';
|
||||||
|
}
|
||||||
|
if (self::where('name', $name)->find()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$data[] = [
|
||||||
|
'name' => $name,
|
||||||
|
'plugin' => $plugin_name,
|
||||||
|
'description' => $description,
|
||||||
|
'create_time' => request()->time(),
|
||||||
|
'update_time' => request()->time(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (!empty($data) && false === self::insertAll($data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除钩子
|
||||||
|
* @param string $plugin_name 钩子名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public static function deleteHooks($plugin_name = '')
|
||||||
|
{
|
||||||
|
if (!empty($plugin_name)) {
|
||||||
|
if (false === self::where('plugin', $plugin_name)->delete()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
122
application/admin/model/HookPlugin.php
Normal file
122
application/admin/model/HookPlugin.php
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use app\admin\model\Hook as HookModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钩子-插件模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class HookPlugin extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_hook_plugin';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用插件钩子
|
||||||
|
* @param string $plugin 插件名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function enable($plugin = '')
|
||||||
|
{
|
||||||
|
return self::where('plugin', $plugin)->setField('status', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用插件钩子
|
||||||
|
* @param string $plugin 插件名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function disable($plugin = '')
|
||||||
|
{
|
||||||
|
return self::where('plugin', $plugin)->setField('status', 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加钩子-插件对照
|
||||||
|
* @param array $hooks 钩子
|
||||||
|
* @param string $plugin_name 插件名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool|int|string
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public static function addHooks($hooks = [], $plugin_name = '')
|
||||||
|
{
|
||||||
|
if (!empty($hooks) && is_array($hooks)) {
|
||||||
|
// 添加钩子
|
||||||
|
if (!HookModel::addHooks($hooks, $plugin_name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
foreach ($hooks as $name => $description) {
|
||||||
|
if (is_numeric($name)) {
|
||||||
|
$name = $description;
|
||||||
|
}
|
||||||
|
$data[] = [
|
||||||
|
'hook' => $name,
|
||||||
|
'plugin' => $plugin_name,
|
||||||
|
'create_time' => request()->time(),
|
||||||
|
'update_time' => request()->time(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::insertAll($data);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除钩子
|
||||||
|
* @param string $plugin_name 钩子名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public static function deleteHooks($plugin_name = '')
|
||||||
|
{
|
||||||
|
if (!empty($plugin_name)) {
|
||||||
|
// 删除钩子
|
||||||
|
if (!HookModel::deleteHooks($plugin_name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (false === self::where('plugin', $plugin_name)->delete()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钩子插件排序
|
||||||
|
* @param string $hook 钩子
|
||||||
|
* @param string $plugins 插件名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function sort($hook = '', $plugins = '')
|
||||||
|
{
|
||||||
|
if ($hook != '' && $plugins != '') {
|
||||||
|
$plugins = is_array($plugins) ? $plugins : explode(',', $plugins);
|
||||||
|
|
||||||
|
foreach ($plugins as $key => $plugin) {
|
||||||
|
$map = [
|
||||||
|
'hook' => $hook,
|
||||||
|
'plugin' => $plugin
|
||||||
|
];
|
||||||
|
self::where($map)->setField('sort', $key + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
55
application/admin/model/Icon.php
Normal file
55
application/admin/model/Icon.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Icon extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_icon';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\model\relation\HasMany
|
||||||
|
*/
|
||||||
|
public function icons()
|
||||||
|
{
|
||||||
|
return $this->hasMany('IconList', 'icon_id')->field('title,class,code');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图标css链接
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|string|\think\Collection
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public static function getUrls()
|
||||||
|
{
|
||||||
|
$list = self::where('status', 1)->select();
|
||||||
|
if ($list) {
|
||||||
|
foreach ($list as $key => $item) {
|
||||||
|
if ($item['icons']) {
|
||||||
|
$html = '<ul class="js-icon-list items-push-2x text-center">';
|
||||||
|
foreach ($item['icons'] as $icon) {
|
||||||
|
$html .= '<li title="'.$icon['title'].'"><i class="'.$icon['class'].'"></i> <code>'.$icon['code'].'</code></li>';
|
||||||
|
}
|
||||||
|
$html .= '</ul>';
|
||||||
|
} else {
|
||||||
|
$html = '<p class="text-center text-muted">暂无图标</p>';
|
||||||
|
}
|
||||||
|
$list[$key]['html'] = $html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
}
|
24
application/admin/model/IconList.php
Normal file
24
application/admin/model/IconList.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标列表模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class IconList extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_icon_list';
|
||||||
|
}
|
37
application/admin/model/Log.php
Normal file
37
application/admin/model/Log.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志记录模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Log extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_log';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有日志
|
||||||
|
* @param array $map 条件
|
||||||
|
* @param string $order 排序
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\Paginator
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public static function getAll($map = [], $order = '')
|
||||||
|
{
|
||||||
|
$data_list = self::view('admin_log', true)
|
||||||
|
->view('admin_action', 'title,module', 'admin_action.id=admin_log.action_id', 'left')
|
||||||
|
->view('admin_user', 'username', 'admin_user.id=admin_log.user_id', 'left')
|
||||||
|
->view('admin_module', ['title' => 'module_title'], 'admin_module.name=admin_action.module')
|
||||||
|
->where($map)
|
||||||
|
->order($order)
|
||||||
|
->paginate();
|
||||||
|
return $data_list;
|
||||||
|
}
|
||||||
|
}
|
322
application/admin/model/Menu.php
Normal file
322
application/admin/model/Menu.php
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use app\user\model\Role as RoleModel;
|
||||||
|
use think\Model;
|
||||||
|
use think\Exception;
|
||||||
|
use util\Tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Menu extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $table = '__ADMIN_MENU__';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
// 将节点url转为小写
|
||||||
|
public function setUrlValueAttr($value)
|
||||||
|
{
|
||||||
|
return strtolower(trim($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归修改所属模型
|
||||||
|
* @param int $id 父级节点id
|
||||||
|
* @param string $module 模型名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function changeModule($id = 0, $module = '')
|
||||||
|
{
|
||||||
|
if ($id > 0) {
|
||||||
|
$ids = self::where('pid', $id)->column('id');
|
||||||
|
if ($ids) {
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
self::where('id', $id)->setField('module', $module);
|
||||||
|
self::changeModule($id, $module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取树形节点
|
||||||
|
* @param int $id 需要隐藏的节点id
|
||||||
|
* @param string $default 默认第一个节点项,默认为“顶级节点”,如果为false则不显示,也可传入其他名称
|
||||||
|
* @param string $module 模型名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function getMenuTree($id = 0, $default = '', $module = '')
|
||||||
|
{
|
||||||
|
$result[0] = '顶级节点';
|
||||||
|
$where = [
|
||||||
|
['status', 'egt', 0]
|
||||||
|
];
|
||||||
|
if ($module != '') {
|
||||||
|
$where[] = ['module', '=', $module];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排除指定节点及其子节点
|
||||||
|
if ($id !== 0) {
|
||||||
|
$hide_ids = array_merge([$id], self::getChildsId($id));
|
||||||
|
$where[] = ['id', 'not in', $hide_ids];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取节点
|
||||||
|
$menus = Tree::toList(self::where($where)->order('pid,id')->column('id,pid,title'));
|
||||||
|
foreach ($menus as $menu) {
|
||||||
|
$result[$menu['id']] = $menu['title_display'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置默认节点项标题
|
||||||
|
if ($default != '') {
|
||||||
|
$result[0] = $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏默认节点项
|
||||||
|
if ($default === false) {
|
||||||
|
unset($result[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取顶部节点
|
||||||
|
* @param string $max 最多返回多少个
|
||||||
|
* @param string $cache_tag 缓存标签
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getTopMenu($max = '', $cache_tag = '')
|
||||||
|
{
|
||||||
|
$cache_tag .= '_role_'.session('user_auth.role');
|
||||||
|
$menus = cache($cache_tag);
|
||||||
|
if (!$menus) {
|
||||||
|
// 非开发模式,只显示可以显示的菜单
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
$map['online_hide'] = 0;
|
||||||
|
}
|
||||||
|
$map['status'] = 1;
|
||||||
|
$map['pid'] = 0;
|
||||||
|
$list_menu = self::where($map)->order('sort,id')->column('id,pid,module,title,url_value,url_type,url_target,icon,params');
|
||||||
|
$i = 0;
|
||||||
|
$menus = [];
|
||||||
|
foreach ($list_menu as $key => &$menu) {
|
||||||
|
if ($max != '' && $i >= $max) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 没有访问权限的节点不显示
|
||||||
|
if (!RoleModel::checkAuth($menu['id'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($menu['url_value'] != '' && ($menu['url_type'] == 'module_admin' || $menu['url_type'] == 'module_home')) {
|
||||||
|
$url = explode('/', $menu['url_value']);
|
||||||
|
$menu['controller'] = $url[1];
|
||||||
|
$menu['action'] = $url[2];
|
||||||
|
$menu['url_value'] = $menu['url_type'] == 'module_admin' ? admin_url($menu['url_value'], $menu['params']) : home_url($menu['url_value'], $menu['params']);
|
||||||
|
}
|
||||||
|
$menus[$key] = $menu;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
// 非开发模式,缓存菜单
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache($cache_tag, $menus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $menus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取侧栏节点
|
||||||
|
* @param string $id 模块id
|
||||||
|
* @param string $module 模块名
|
||||||
|
* @param string $controller 控制器名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getSidebarMenu($id = '', $module = '', $controller = '')
|
||||||
|
{
|
||||||
|
$module = $module == '' ? request()->module() : $module;
|
||||||
|
$controller = $controller == '' ? request()->controller() : $controller;
|
||||||
|
$cache_tag = strtolower('_sidebar_menus_' . $module . '_' . $controller).'_role_'.session('user_auth.role');
|
||||||
|
$menus = cache($cache_tag);
|
||||||
|
|
||||||
|
if (!$menus) {
|
||||||
|
// 获取当前节点地址
|
||||||
|
$location = self::getLocation($id);
|
||||||
|
// 当前顶级节点id
|
||||||
|
$top_id = $location[0]['id'];
|
||||||
|
// 获取顶级节点下的所有节点
|
||||||
|
$map = [
|
||||||
|
'status' => 1
|
||||||
|
];
|
||||||
|
// 非开发模式,只显示可以显示的菜单
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
$map['online_hide'] = 0;
|
||||||
|
}
|
||||||
|
$menus = self::where($map)->order('sort,id')->column('id,pid,module,title,url_value,url_type,url_target,icon,params');
|
||||||
|
|
||||||
|
// 解析模块链接
|
||||||
|
foreach ($menus as $key => &$menu) {
|
||||||
|
// 没有访问权限的节点不显示
|
||||||
|
if (!RoleModel::checkAuth($menu['id'])) {
|
||||||
|
unset($menus[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($menu['url_value'] != '' && ($menu['url_type'] == 'module_admin' || $menu['url_type'] == 'module_home')) {
|
||||||
|
$menu['url_value'] = $menu['url_type'] == 'module_admin' ? admin_url($menu['url_value'], $menu['params']) : home_url($menu['url_value'], $menu['params']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$menus = Tree::toLayer($menus, $top_id, 2);
|
||||||
|
|
||||||
|
// 非开发模式,缓存菜单
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache($cache_tag, $menus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $menus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定节点ID的位置
|
||||||
|
* @param string $id 节点id,如果没有指定,则取当前节点id
|
||||||
|
* @param bool $del_last_url 是否删除最后一个节点的url地址
|
||||||
|
* @param bool $check 检查节点是否存在,不存在则抛出错误
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public static function getLocation($id = '', $del_last_url = false, $check = true)
|
||||||
|
{
|
||||||
|
$model = request()->module();
|
||||||
|
$controller = request()->controller();
|
||||||
|
$action = request()->action();
|
||||||
|
|
||||||
|
if ($id != '') {
|
||||||
|
$cache_name = 'location_menu_'.$id;
|
||||||
|
} else {
|
||||||
|
$cache_name = 'location_'.$model.'_'.$controller.'_'.$action;
|
||||||
|
}
|
||||||
|
|
||||||
|
$location = cache($cache_name);
|
||||||
|
|
||||||
|
if (!$location) {
|
||||||
|
$map = [
|
||||||
|
['pid', '<>', 0],
|
||||||
|
['url_value', '=', strtolower($model.'/'.trim(preg_replace("/[A-Z]/", "_\\0", $controller), "_").'/'.$action)]
|
||||||
|
];
|
||||||
|
|
||||||
|
// 当前操作对应的节点ID
|
||||||
|
$curr_id = $id == '' ? self::where($map)->value('id') : $id;
|
||||||
|
|
||||||
|
// 获取节点ID是所有父级节点
|
||||||
|
$location = Tree::getParents(self::column('id,pid,title,url_value,params'), $curr_id);
|
||||||
|
|
||||||
|
if ($check && empty($location)) {
|
||||||
|
throw new Exception('获取不到当前节点地址,可能未添加节点', 9001);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 剔除最后一个节点url
|
||||||
|
if ($del_last_url) {
|
||||||
|
$location[count($location) - 1]['url_value'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非开发模式,缓存菜单
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache($cache_name, $location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据分组获取节点
|
||||||
|
* @param string $group 分组名称
|
||||||
|
* @param bool|string $fields 要返回的字段
|
||||||
|
* @param array $map 查找条件
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getMenusByGroup($group = '', $fields = true, $map = [])
|
||||||
|
{
|
||||||
|
$map['module'] = $group;
|
||||||
|
return self::where($map)->order('sort,id')->column($fields, 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点分组
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getGroup()
|
||||||
|
{
|
||||||
|
$map['status'] = 1;
|
||||||
|
$map['pid'] = 0;
|
||||||
|
$menus = self::where($map)->order('id,sort')->column('module,title');
|
||||||
|
return $menus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有子节点id
|
||||||
|
* @param int $pid 父级id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getChildsId($pid = 0)
|
||||||
|
{
|
||||||
|
$ids = self::where('pid', $pid)->column('id');
|
||||||
|
foreach ($ids as $value) {
|
||||||
|
$ids = array_merge($ids, self::getChildsId($value));
|
||||||
|
}
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有父节点id
|
||||||
|
* @param int $id 节点id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getParentsId($id = 0)
|
||||||
|
{
|
||||||
|
$pid = self::where('id', $id)->value('pid');
|
||||||
|
$pids = [];
|
||||||
|
if ($pid != 0) {
|
||||||
|
$pids[] = $pid;
|
||||||
|
$pids = array_merge($pids, self::getParentsId($pid));
|
||||||
|
}
|
||||||
|
return $pids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据节点id获取上下级的所有id
|
||||||
|
* @param int $id 节点id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getLinkIds($id = 0)
|
||||||
|
{
|
||||||
|
$childs = self::getChildsId($id);
|
||||||
|
$parents = self::getParentsId($id);
|
||||||
|
return array_merge((array)(int)$id, $childs, $parents);
|
||||||
|
}
|
||||||
|
}
|
343
application/admin/model/Module.php
Normal file
343
application/admin/model/Module.php
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\facade\Env;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模块模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Module extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $table = '__ADMIN_MODULE__';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有模块的名称和标题
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function getModule()
|
||||||
|
{
|
||||||
|
$modules = cache('modules');
|
||||||
|
if (!$modules) {
|
||||||
|
$modules = self::where('status', '>=', 0)->order('id')->column('name,title');
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('modules', $modules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $modules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有模块信息
|
||||||
|
* @param string $keyword 查找关键词
|
||||||
|
* @param string $status 查找状态
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
public function getAll($keyword = '', $status = '')
|
||||||
|
{
|
||||||
|
$result = cache('module_all');
|
||||||
|
if (!$result) {
|
||||||
|
$dirs = array_map('basename', glob(Env::get('app_path').'*', GLOB_ONLYDIR));
|
||||||
|
if ($dirs === false || !file_exists(Env::get('app_path'))) {
|
||||||
|
$this->error = '模块目录不可读或者不存在';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不读取模块信息的目录
|
||||||
|
$except_module = config('system.except_module');
|
||||||
|
// 正常模块(包括已安装和未安装)
|
||||||
|
$dirs = array_diff($dirs, $except_module);
|
||||||
|
|
||||||
|
// 读取数据库模块表
|
||||||
|
$modules = $this->order('sort asc,id desc')->column(true, 'name');
|
||||||
|
|
||||||
|
// 读取未安装的模块
|
||||||
|
foreach ($dirs as $module) {
|
||||||
|
if (!isset($modules[$module])) {
|
||||||
|
// 获取模块信息
|
||||||
|
$info = self::getInfoFromFile($module);
|
||||||
|
|
||||||
|
$modules[$module]['name'] = $module;
|
||||||
|
|
||||||
|
// 模块模块信息缺失
|
||||||
|
if (empty($info)) {
|
||||||
|
$modules[$module]['status'] = '-2';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模块模块信息不完整
|
||||||
|
if (!$this->checkInfo($info)) {
|
||||||
|
$modules[$module]['status'] = '-3';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模块未安装
|
||||||
|
$modules[$module] = $info;
|
||||||
|
$modules[$module]['status'] = '-1'; // 模块未安装
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数量统计
|
||||||
|
$total = [
|
||||||
|
'all' => count($modules), // 所有模块数量
|
||||||
|
'-2' => 0, // 已损坏数量
|
||||||
|
'-1' => 0, // 未安装数量
|
||||||
|
'0' => 0, // 已禁用数量
|
||||||
|
'1' => 0, // 已启用数量
|
||||||
|
];
|
||||||
|
|
||||||
|
// 过滤查询结果和统计数量
|
||||||
|
foreach ($modules as $key => $value) {
|
||||||
|
// 统计数量
|
||||||
|
if (in_array($value['status'], ['-2', '-3'])) {
|
||||||
|
// 已损坏数量
|
||||||
|
$total['-2']++;
|
||||||
|
} else {
|
||||||
|
$total[(string)$value['status']]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤查询
|
||||||
|
if ($status != '') {
|
||||||
|
if ($status == '-2') {
|
||||||
|
// 过滤掉非已损坏的模块
|
||||||
|
if (!in_array($value['status'], ['-2', '-3'])) {
|
||||||
|
unset($modules[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if ($value['status'] != $status) {
|
||||||
|
unset($modules[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($keyword != '') {
|
||||||
|
if (stristr($value['name'], $keyword) === false && (!isset($value['title']) || stristr($value['title'], $keyword) === false) && (!isset($value['author']) || stristr($value['author'], $keyword) === false)) {
|
||||||
|
unset($modules[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理状态及模块按钮
|
||||||
|
foreach ($modules as &$module) {
|
||||||
|
// 系统核心模块
|
||||||
|
if (isset($module['system_module']) && $module['system_module'] == '1') {
|
||||||
|
$module['actions'] = '<button class="btn btn-sm btn-noborder btn-danger" type="button" disabled>不可操作</button>';
|
||||||
|
$module['status_class'] = 'text-success';
|
||||||
|
$module['status_info'] = '<i class="fa fa-check"></i> 已启用';
|
||||||
|
$module['bg_color'] = 'success';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($module['status']) {
|
||||||
|
case '-3': // 模块信息不完整
|
||||||
|
$module['title'] = '模块信息不完整';
|
||||||
|
$module['bg_color'] = 'danger';
|
||||||
|
$module['status_class'] = 'text-danger';
|
||||||
|
$module['status_info'] = '<i class="fa fa-times"></i> 已损坏';
|
||||||
|
$module['actions'] = '<button class="btn btn-sm btn-noborder btn-danger" type="button" disabled>不可操作</button>';
|
||||||
|
break;
|
||||||
|
case '-2': // 模块信息缺失
|
||||||
|
$module['title'] = '模块信息缺失';
|
||||||
|
$module['bg_color'] = 'danger';
|
||||||
|
$module['status_class'] = 'text-danger';
|
||||||
|
$module['status_info'] = '<i class="fa fa-times"></i> 已损坏';
|
||||||
|
$module['actions'] = '<button class="btn btn-sm btn-noborder btn-danger" type="button" disabled>不可操作</button>';
|
||||||
|
break;
|
||||||
|
case '-1': // 未安装
|
||||||
|
$module['bg_color'] = 'info';
|
||||||
|
$module['actions'] = '<a class="btn btn-sm btn-noborder btn-success" href="'.url('install', ['name' => $module['name']]).'">安装</a>';
|
||||||
|
$module['status_class'] = 'text-info';
|
||||||
|
$module['status_info'] = '<i class="fa fa-fw fa-th-large"></i> 未安装';
|
||||||
|
break;
|
||||||
|
case '0': // 禁用
|
||||||
|
$module['bg_color'] = 'warning';
|
||||||
|
$module['actions'] = '<a class="btn btn-sm btn-noborder btn-success ajax-get confirm" href="'.url('enable', ['ids' => $module['id']]).'">启用</a> ';
|
||||||
|
$module['actions'] .= '<a class="btn btn-sm btn-noborder btn-primary" href="'.url('export', ['name' => $module['name']]).'">导出</a> ';
|
||||||
|
$module['actions'] .= '<a class="btn btn-sm btn-noborder btn-danger" href="'.url('uninstall', ['name' => $module['name']]).'">卸载</a> ';
|
||||||
|
$module['status_class'] = 'text-warning';
|
||||||
|
$module['status_info'] = '<i class="fa fa-ban"></i> 已禁用';
|
||||||
|
break;
|
||||||
|
case '1': // 启用
|
||||||
|
$module['bg_color'] = 'success';
|
||||||
|
$module['actions'] = '<a class="btn btn-sm btn-noborder btn-info ajax-get confirm" href="'.url('update', ['name' => $module['name']]).'">更新</a> ';
|
||||||
|
$module['actions'] .= '<a class="btn btn-sm btn-noborder btn-warning ajax-get confirm" href="'.url('disable', ['ids' => $module['id']]).'">禁用</a> ';
|
||||||
|
$module['actions'] .= '<a class="btn btn-sm btn-noborder btn-primary" href="'.url('export', ['name' => $module['name']]).'">导出</a> ';
|
||||||
|
$module['actions'] .= '<a class="btn btn-sm btn-noborder btn-danger" href="'.url('uninstall', ['name' => $module['name']]).'">卸载</a> ';
|
||||||
|
$module['status_class'] = 'text-success';
|
||||||
|
$module['status_info'] = '<i class="fa fa-check"></i> 已启用';
|
||||||
|
break;
|
||||||
|
default: // 未知
|
||||||
|
$module['title'] = '未知';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = ['total' => $total, 'modules' => $modules];
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('module_all', $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件获取模块信息
|
||||||
|
* @param string $name 模块名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getInfoFromFile($name = '')
|
||||||
|
{
|
||||||
|
$info = [];
|
||||||
|
if ($name != '') {
|
||||||
|
// 从配置文件获取
|
||||||
|
if (is_file(Env::get('app_path'). $name . '/info.php')) {
|
||||||
|
$info = include Env::get('app_path'). $name . '/info.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查模块模块信息是否完整
|
||||||
|
* @param string $info 模块模块信息
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkInfo($info = '')
|
||||||
|
{
|
||||||
|
$default_item = ['name','title','author','version'];
|
||||||
|
foreach ($default_item as $item) {
|
||||||
|
if (!isset($info[$item]) || $info[$item] == '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取模型配置信息
|
||||||
|
* @param string $name 模型名
|
||||||
|
* @param string $item 指定返回的模块配置项
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function getConfig($name = '', $item = '')
|
||||||
|
{
|
||||||
|
$name = $name == '' ? request()->module() : $name;
|
||||||
|
|
||||||
|
$config = cache('module_config_'.$name);
|
||||||
|
if (!$config) {
|
||||||
|
$config = self::where('name', $name)->value('config');
|
||||||
|
if (!$config) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = json_decode($config, true);
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('module_config_'.$name, $config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($item)) {
|
||||||
|
$items = explode(',', $item);
|
||||||
|
if (count($items) == 1) {
|
||||||
|
return isset($config[$item]) ? $config[$item] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$result[$item] = isset($config[$item]) ? $config[$item] : '';
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取模型配置信息
|
||||||
|
* @param string $name 插件名.配置名
|
||||||
|
* @param string $value 配置值
|
||||||
|
* @author caiweiming <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function setConfig($name = '', $value = '')
|
||||||
|
{
|
||||||
|
$item = '';
|
||||||
|
if (strpos($name, '.')) {
|
||||||
|
list($name, $item) = explode('.', $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取缓存
|
||||||
|
$config = cache('module_config_'.$name);
|
||||||
|
|
||||||
|
if (!$config) {
|
||||||
|
$config = self::where('name', $name)->value('config');
|
||||||
|
if (!$config) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = json_decode($config, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item === '') {
|
||||||
|
// 批量更新
|
||||||
|
if (!is_array($value) || empty($value)) {
|
||||||
|
// 值的格式错误,必须为数组
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = array_merge($config, $value);
|
||||||
|
} else {
|
||||||
|
// 更新单个值
|
||||||
|
$config[$item] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === self::where('name', $name)->setField('config', json_encode($config))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('module_config_'.$name, $config);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件获取模块菜单
|
||||||
|
* @param string $name 模块名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getMenusFromFile($name = '')
|
||||||
|
{
|
||||||
|
$menus = [];
|
||||||
|
if ($name != '' && is_file(Env::get('app_path'). $name . '/menus.php')) {
|
||||||
|
// 从菜单文件获取
|
||||||
|
$menus = include Env::get('app_path'). $name . '/menus.php';
|
||||||
|
}
|
||||||
|
return $menus;
|
||||||
|
}
|
||||||
|
}
|
117
application/admin/model/Packet.php
Normal file
117
application/admin/model/Packet.php
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\Db;
|
||||||
|
use util\Sql;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据包模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Packet extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_packet';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有数据包列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
public function getAll()
|
||||||
|
{
|
||||||
|
// 获取数据包目录下的所有插件目录
|
||||||
|
$dirs = array_map('basename', glob(config('packet_path').'*', GLOB_ONLYDIR));
|
||||||
|
if ($dirs === false || !file_exists(config('packet_path'))) {
|
||||||
|
$this->error = '插件目录不可读或者不存在';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取数据库数据包表
|
||||||
|
$packets = $this->column(true, 'name');
|
||||||
|
|
||||||
|
// 读取未安装的数据包
|
||||||
|
foreach ($dirs as $packet) {
|
||||||
|
if (!isset($packets[$packet])) {
|
||||||
|
$info = $this->getInfoFromFile($packet);
|
||||||
|
$info['status'] = 0;
|
||||||
|
$packets[] = $info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件获取数据包信息
|
||||||
|
* @param string $name 数据包名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getInfoFromFile($name = '')
|
||||||
|
{
|
||||||
|
$info = [];
|
||||||
|
if ($name != '') {
|
||||||
|
// 从配置文件获取
|
||||||
|
if (is_file(config('packet_path'). $name . '/info.php')) {
|
||||||
|
$info = include config('packet_path'). $name . '/info.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安装数据包
|
||||||
|
* @param string $name 数据包名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function install($name = '')
|
||||||
|
{
|
||||||
|
$info = self::getInfoFromFile($name);
|
||||||
|
|
||||||
|
foreach ($info['tables'] as $table) {
|
||||||
|
$sql_file = realpath(config('packet_path').$name."/{$table}.sql");
|
||||||
|
if (file_exists($sql_file)) {
|
||||||
|
if (isset($info['database_prefix']) && $info['database_prefix'] != '') {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file, false, [$info['database_prefix'] => config('database.prefix')]);
|
||||||
|
} else {
|
||||||
|
$sql_statement = Sql::getSqlFromFile($sql_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($sql_statement)) {
|
||||||
|
foreach ($sql_statement as $value) {
|
||||||
|
Db::execute($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "【{$table}.sql】文件不存在";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卸载数据包
|
||||||
|
* @param string $name 数据包名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public static function uninstall($name = '')
|
||||||
|
{
|
||||||
|
$info = self::getInfoFromFile($name);
|
||||||
|
foreach ($info['tables'] as $table) {
|
||||||
|
$sql = "DROP TABLE IF EXISTS `". config('database.prefix') ."{$table}`;";
|
||||||
|
Db::execute($sql);
|
||||||
|
self::where('name', $name)->delete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
299
application/admin/model/Plugin.php
Normal file
299
application/admin/model/Plugin.php
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件模型
|
||||||
|
* @package app\admin\model
|
||||||
|
*/
|
||||||
|
class Plugin extends Model
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'admin_plugin';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
// 写入时处理config
|
||||||
|
public function setConfigAttr($value)
|
||||||
|
{
|
||||||
|
return !empty($value) ? json_encode($value) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有插件信息
|
||||||
|
* @param string $keyword 查找关键词
|
||||||
|
* @param string $status 查找状态
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
public function getAll($keyword = '', $status = '')
|
||||||
|
{
|
||||||
|
$result = cache('plugin_all');
|
||||||
|
if (!$result) {
|
||||||
|
// 获取插件目录下的所有插件目录
|
||||||
|
$dirs = array_map('basename', glob(config('plugin_path').'*', GLOB_ONLYDIR));
|
||||||
|
if ($dirs === false || !file_exists(config('plugin_path'))) {
|
||||||
|
$this->error = '插件目录不可读或者不存在';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取数据库插件表
|
||||||
|
$plugins = $this->order('sort asc,id desc')->column(true, 'name');
|
||||||
|
|
||||||
|
// 读取未安装的插件
|
||||||
|
foreach ($dirs as $plugin) {
|
||||||
|
if (!isset($plugins[$plugin])) {
|
||||||
|
$plugins[$plugin]['name'] = $plugin;
|
||||||
|
|
||||||
|
// 获取插件类名
|
||||||
|
$class = get_plugin_class($plugin);
|
||||||
|
|
||||||
|
// 插件类不存在则跳过实例化
|
||||||
|
if (!class_exists($class)) {
|
||||||
|
// 插件的入口文件不存在!
|
||||||
|
$plugins[$plugin]['status'] = '-2';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化插件
|
||||||
|
$obj = new $class;
|
||||||
|
|
||||||
|
// 插件插件信息缺失
|
||||||
|
if (!isset($obj->info) || empty($obj->info)) {
|
||||||
|
// 插件信息缺失!
|
||||||
|
$plugins[$plugin]['status'] = '-3';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插件插件信息不完整
|
||||||
|
if (!$this->checkInfo($obj->info)) {
|
||||||
|
$plugins[$plugin]['status'] = '-4';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插件未安装
|
||||||
|
$plugins[$plugin] = $obj->info;
|
||||||
|
$plugins[$plugin]['status'] = '-1';
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数量统计
|
||||||
|
$total = [
|
||||||
|
'all' => count($plugins), // 所有插件数量
|
||||||
|
'-2' => 0, // 错误插件数量
|
||||||
|
'-1' => 0, // 未安装数量
|
||||||
|
'0' => 0, // 未启用数量
|
||||||
|
'1' => 0, // 已启用数量
|
||||||
|
];
|
||||||
|
|
||||||
|
// 过滤查询结果和统计数量
|
||||||
|
foreach ($plugins as $key => $value) {
|
||||||
|
// 统计数量
|
||||||
|
if (in_array($value['status'], ['-2', '-3', '-4'])) {
|
||||||
|
// 已损坏数量
|
||||||
|
$total['-2']++;
|
||||||
|
} else {
|
||||||
|
$total[(string)$value['status']]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤查询
|
||||||
|
if ($status != '') {
|
||||||
|
if ($status == '-2') {
|
||||||
|
// 过滤掉非已损坏的插件
|
||||||
|
if (!in_array($value['status'], ['-2', '-3', '-4'])) {
|
||||||
|
unset($plugins[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if ($value['status'] != $status) {
|
||||||
|
unset($plugins[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($keyword != '') {
|
||||||
|
if (stristr($value['name'], $keyword) === false && (!isset($value['title']) || stristr($value['title'], $keyword) === false) && (!isset($value['author']) || stristr($value['author'], $keyword) === false)) {
|
||||||
|
unset($plugins[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理状态及插件按钮
|
||||||
|
foreach ($plugins as &$plugin) {
|
||||||
|
switch ($plugin['status']) {
|
||||||
|
case '-4': // 插件信息不完整
|
||||||
|
$plugin['title'] = '插件信息不完整';
|
||||||
|
$plugin['bg_color'] = 'danger';
|
||||||
|
$plugin['status_class'] = 'text-danger';
|
||||||
|
$plugin['status_info'] = '<i class="fa fa-times"></i> 已损坏';
|
||||||
|
$plugin['actions'] = '<button class="btn btn-sm btn-noborder btn-danger" type="button" disabled>不可操作</button>';
|
||||||
|
break;
|
||||||
|
case '-3': // 插件信息缺失
|
||||||
|
$plugin['title'] = '插件信息缺失';
|
||||||
|
$plugin['bg_color'] = 'danger';
|
||||||
|
$plugin['status_class'] = 'text-danger';
|
||||||
|
$plugin['status_info'] = '<i class="fa fa-times"></i> 已损坏';
|
||||||
|
$plugin['actions'] = '<button class="btn btn-sm btn-noborder btn-danger" type="button" disabled>不可操作</button>';
|
||||||
|
break;
|
||||||
|
case '-2': // 入口文件不存在
|
||||||
|
$plugin['title'] = '入口文件不存在';
|
||||||
|
$plugin['bg_color'] = 'danger';
|
||||||
|
$plugin['status_class'] = 'text-danger';
|
||||||
|
$plugin['status_info'] = '<i class="fa fa-times"></i> 已损坏';
|
||||||
|
$plugin['actions'] = '<button class="btn btn-sm btn-noborder btn-danger" type="button" disabled>不可操作</button>';
|
||||||
|
break;
|
||||||
|
case '-1': // 未安装
|
||||||
|
$plugin['bg_color'] = 'info';
|
||||||
|
$plugin['actions'] = '<a class="btn btn-sm btn-noborder btn-success ajax-get confirm" href="'.url('install', ['name' => $plugin['name']]).'">安装</a>';
|
||||||
|
$plugin['status_class'] = 'text-info';
|
||||||
|
$plugin['status_info'] = '<i class="fa fa-fw fa-th-large"></i> 未安装';
|
||||||
|
break;
|
||||||
|
case '0': // 禁用
|
||||||
|
$plugin['bg_color'] = 'warning';
|
||||||
|
$plugin['actions'] = '<a class="btn btn-sm btn-noborder btn-success ajax-get confirm" href="'.url('enable', ['ids' => $plugin['id']]).'">启用</a> ';
|
||||||
|
$plugin['actions'] .= '<a class="btn btn-sm btn-noborder btn-danger ajax-get confirm" data-tips="如果包括数据库,将同时删除数据库!" href="'.url('uninstall', ['name' => $plugin['name']]).'">卸载</a> ';
|
||||||
|
if (isset($plugin['config']) && $plugin['config'] != '') {
|
||||||
|
$plugin['actions'] .= '<a class="btn btn-sm btn-noborder btn-info" href="'.url('config', ['name' => $plugin['name']]).'">设置</a> ';
|
||||||
|
}
|
||||||
|
if ($plugin['admin'] != '0') {
|
||||||
|
$plugin['actions'] .= '<a class="btn btn-sm btn-noborder btn-primary" href="'.url('manage', ['name' => $plugin['name']]).'">管理</a> ';
|
||||||
|
}
|
||||||
|
$plugin['status_class'] = 'text-warning';
|
||||||
|
$plugin['status_info'] = '<i class="fa fa-ban"></i> 已禁用';
|
||||||
|
break;
|
||||||
|
case '1': // 启用
|
||||||
|
$plugin['bg_color'] = 'success';
|
||||||
|
$plugin['actions'] = '<a class="btn btn-sm btn-noborder btn-warning ajax-get confirm" href="'.url('disable', ['ids' => $plugin['id']]).'">禁用</a> ';
|
||||||
|
$plugin['actions'] .= '<a class="btn btn-sm btn-noborder btn-danger ajax-get confirm" data-tips="如果包括数据库,将同时删除数据库!" href="'.url('uninstall', ['name' => $plugin['name']]).'">卸载</a> ';
|
||||||
|
if (isset($plugin['config']) && $plugin['config'] != '') {
|
||||||
|
$plugin['actions'] .= '<a class="btn btn-sm btn-noborder btn-info" href="'.url('config', ['name' => $plugin['name']]).'">设置</a> ';
|
||||||
|
}
|
||||||
|
if ($plugin['admin'] != '0') {
|
||||||
|
$plugin['actions'] .= '<a class="btn btn-sm btn-noborder btn-primary" href="'.url('manage', ['name' => $plugin['name']]).'">管理</a> ';
|
||||||
|
}
|
||||||
|
$plugin['status_class'] = 'text-success';
|
||||||
|
$plugin['status_info'] = '<i class="fa fa-check"></i> 已启用';
|
||||||
|
break;
|
||||||
|
default: // 未知
|
||||||
|
$plugin['title'] = '未知';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = ['total' => $total, 'plugins' => $plugins];
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('plugin_all', $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查插件插件信息是否完整
|
||||||
|
* @param string $info 插件插件信息
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkInfo($info = '')
|
||||||
|
{
|
||||||
|
$default_item = ['name','title','author','version'];
|
||||||
|
foreach ($default_item as $item) {
|
||||||
|
if (!isset($info[$item]) || $info[$item] == '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取插件配置
|
||||||
|
* @param string $name 插件名称
|
||||||
|
* @param string $item 指定返回的插件配置项
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public function getConfig($name = '', $item = '')
|
||||||
|
{
|
||||||
|
$config = cache('plugin_config_'.$name);
|
||||||
|
if (!$config) {
|
||||||
|
$config = $this->where('name', $name)->value('config');
|
||||||
|
if (!$config) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = json_decode($config, true);
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('plugin_config_'.$name, $config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($item)) {
|
||||||
|
$items = explode(',', $item);
|
||||||
|
if (count($items) == 1) {
|
||||||
|
return isset($config[$item]) ? $config[$item] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$result[$item] = isset($config[$item]) ? $config[$item] : '';
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置插件配置
|
||||||
|
* @param string $name 插件名.配置名
|
||||||
|
* @param string $value 配置值
|
||||||
|
* @author caiweiming <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function setConfig($name = '', $value = '')
|
||||||
|
{
|
||||||
|
$item = '';
|
||||||
|
if (strpos($name, '.')) {
|
||||||
|
list($name, $item) = explode('.', $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取缓存
|
||||||
|
$config = cache('plugin_config_'.$name);
|
||||||
|
|
||||||
|
if (!$config) {
|
||||||
|
$config = $this->where('name', $name)->value('config');
|
||||||
|
if (!$config) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = json_decode($config, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item === '') {
|
||||||
|
// 批量更新
|
||||||
|
if (!is_array($value) || empty($value)) {
|
||||||
|
// 值的格式错误,必须为数组
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = array_merge($config, $value);
|
||||||
|
} else {
|
||||||
|
// 更新单个值
|
||||||
|
$config[$item] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->where('name', $name)->setField('config', json_encode($config))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('plugin_config_'.$name, $config);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
25
application/admin/validate/Action.php
Normal file
25
application/admin/validate/Action.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行为验证器
|
||||||
|
* @package app\admin\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Action extends Validate
|
||||||
|
{
|
||||||
|
//定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'module|所属模块' => 'require',
|
||||||
|
'name|行为标识' => 'require|regex:^[a-zA-Z]\w{0,39}$|unique:admin_action,name^module',
|
||||||
|
'title|行为名称' => 'require|length:1,80',
|
||||||
|
'remark|行为描述' => 'require|length:1,128'
|
||||||
|
];
|
||||||
|
|
||||||
|
//定义验证提示
|
||||||
|
protected $message = [
|
||||||
|
'name.regex' => '行为标识由字母和下划线组成',
|
||||||
|
];
|
||||||
|
}
|
31
application/admin/validate/Config.php
Normal file
31
application/admin/validate/Config.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置验证器
|
||||||
|
* @package app\admin\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Config extends Validate
|
||||||
|
{
|
||||||
|
// 定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'group|配置分组' => 'require',
|
||||||
|
'type|配置类型' => 'require',
|
||||||
|
'name|配置名称' => 'require|regex:^[a-zA-Z]\w{0,39}$|unique:admin_config',
|
||||||
|
'title|配置标题' => 'require',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 定义验证提示
|
||||||
|
protected $message = [
|
||||||
|
'name.regex' => '配置名称由字母和下划线组成',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 定义场景,供快捷编辑时验证
|
||||||
|
protected $scene = [
|
||||||
|
'name' => ['name'],
|
||||||
|
'title' => ['title'],
|
||||||
|
];
|
||||||
|
}
|
22
application/admin/validate/Hook.php
Normal file
22
application/admin/validate/Hook.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钩子验证器
|
||||||
|
* @package app\admin\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Hook extends Validate
|
||||||
|
{
|
||||||
|
//定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'name|钩子名称' => 'require|regex:^[a-zA-Z]\w{0,39}$|unique:admin_hook'
|
||||||
|
];
|
||||||
|
|
||||||
|
//定义验证提示
|
||||||
|
protected $message = [
|
||||||
|
'name.regex' => '钩子名称由字母和下划线组成',
|
||||||
|
];
|
||||||
|
}
|
25
application/admin/validate/Menu.php
Normal file
25
application/admin/validate/Menu.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点验证器
|
||||||
|
* @package app\admin\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Menu extends Validate
|
||||||
|
{
|
||||||
|
//定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'module|所属模块' => 'require',
|
||||||
|
'pid|所属节点' => 'require',
|
||||||
|
'title|节点标题' => 'require',
|
||||||
|
];
|
||||||
|
|
||||||
|
//定义验证提示
|
||||||
|
protected $message = [
|
||||||
|
'module.require' => '请选择所属模块',
|
||||||
|
'pid.require' => '请选择所属节点',
|
||||||
|
];
|
||||||
|
}
|
18
application/admin/validate/Plugin.php
Normal file
18
application/admin/validate/Plugin.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\admin\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件验证器
|
||||||
|
* @package app\admin\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Plugin extends Validate
|
||||||
|
{
|
||||||
|
//定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'name|插件名称' => 'require|unique:admin_plugin',
|
||||||
|
'title|插件标题' => 'require',
|
||||||
|
];
|
||||||
|
}
|
78
application/admin/view/dispatch_jump.tpl
Normal file
78
application/admin/view/dispatch_jump.tpl
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--[if IE 9]> <html class="ie9 no-focus" lang="zh"> <![endif]-->
|
||||||
|
<!--[if gt IE 9]><!--> <html class="no-focus" lang="zh"> <!--<![endif]-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>跳转提示 | {:config('web_site_title')} - DolphinPHP</title>
|
||||||
|
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1.0">
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<!-- The following icons can be replaced with your own, they are used by desktop and mobile browsers -->
|
||||||
|
<link rel="shortcut icon" href="__STATIC__/img/favicons/favicon.png">
|
||||||
|
<!-- END Icons -->
|
||||||
|
|
||||||
|
<!-- Stylesheets -->
|
||||||
|
<!-- Bootstrap and OneUI CSS framework -->
|
||||||
|
<link rel="stylesheet" href="__ADMIN_CSS__/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="__ADMIN_CSS__/oneui.css">
|
||||||
|
<link rel="stylesheet" href="__ADMIN_CSS__/dolphin.css">
|
||||||
|
<!-- END Stylesheets -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Error Content -->
|
||||||
|
<div class="content bg-white text-center pulldown overflow-hidden">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 col-sm-offset-3">
|
||||||
|
<!-- Error Titles -->
|
||||||
|
<h1 class="font-w300 {$code? 'text-success' : 'text-city'} push-10 animated flipInX"><i class="fa fa-{$code? 'check' : 'times'}-circle"></i> <?php echo(strip_tags($msg));?></h1>
|
||||||
|
<p class="font-w300 push-20 animated fadeInUp">页面自动 <a id="href" href="<?php echo($url);?>">跳转</a> 等待时间: <b id="wait"><?php echo($wait);?></b>秒</p>
|
||||||
|
<div class="push-50">
|
||||||
|
<a class="btn btn-minw btn-rounded btn-success" href="<?php echo($url);?>"><i class="fa fa-external-link-square"></i> 立即跳转</a>
|
||||||
|
<button class="btn btn-minw btn-rounded btn-warning" type="button" onclick="stop()"><i class="fa fa-ban"></i> 禁止跳转</button>
|
||||||
|
<a class="btn btn-minw btn-rounded btn-default" href="{$Request.baseFile}"><i class="fa fa-home"></i> 返回首页</a>
|
||||||
|
</div>
|
||||||
|
<!-- END Error Titles -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- END Error Content -->
|
||||||
|
|
||||||
|
<!-- Error Footer -->
|
||||||
|
<div class="content pulldown text-muted text-center">
|
||||||
|
极简 · 极速 · 极致<br>
|
||||||
|
海豚PHP,让开发更简单!<br>
|
||||||
|
由 <a class="link-effect" href="http://www.dolphinphp.com">DolphinPHP</a> 强力驱动 <a class="link-effect" href="http://www.zrthink.com">卓锐软件</a> 倾情奉献
|
||||||
|
</div>
|
||||||
|
<!-- END Error Footer -->
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function(){
|
||||||
|
let wait = document.getElementById('wait'),
|
||||||
|
href = document.getElementById('href').href,
|
||||||
|
pop = '{$Request.param._pop}'; //获取窗口索引
|
||||||
|
|
||||||
|
let interval = setInterval(function(){
|
||||||
|
let time = --wait.innerHTML;
|
||||||
|
if(time <= 0) {
|
||||||
|
if (pop === '1' && parent.layer !== undefined) {
|
||||||
|
let index = parent.layer.getFrameIndex(window.name);
|
||||||
|
parent.layer.close(index);
|
||||||
|
} else {
|
||||||
|
location.href = href;
|
||||||
|
}
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
// 禁止跳转
|
||||||
|
window.stop = function (){
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
74
application/admin/view/ie/index.html
Normal file
74
application/admin/view/ie/index.html
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-cn">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>页面提示 - {:config('web_site_title')}</title>
|
||||||
|
<link rel=stylesheet type=text/css href="https://wx.gtimg.com/pay/css/common/common.css?v=20170117">
|
||||||
|
<link rel=stylesheet type=text/css href="https://wx.gtimg.com/pay/css/error/error.css?v=20151125">
|
||||||
|
<script src="https://wx.gtimg.com/third/jquery/jquery-1.7.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body class="browser-tips no-nav no-topbar">
|
||||||
|
<div class="container wrap">
|
||||||
|
<div class="container-bd">
|
||||||
|
<div class="page-msg mini">
|
||||||
|
<div class="inner">
|
||||||
|
<div class="msg-ico"><i class="ico-msg-s warn"></i></div>
|
||||||
|
<div class="msg-cnt">
|
||||||
|
<p>温馨提示:在IE浏览器环境下浏览本系统体验不够友好,建议您使用下方的浏览器访问本系统。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="browser-list">
|
||||||
|
<a class="browser-item chrome" href="http://xiazai.sogou.com/detail/34/0/6262355089742005676.html?uID=04583CB73B70900A0000000057318502&w=2295" target="_blank">
|
||||||
|
<i class="icon-browser"></i>
|
||||||
|
<p class="browser-name">Chrome浏览器</p>
|
||||||
|
</a>
|
||||||
|
<a class="browser-item qq" href="http://browser.qq.com/" target="_blank">
|
||||||
|
<i class="icon-browser"></i>
|
||||||
|
<p class="browser-name">QQ浏览器</p>
|
||||||
|
</a>
|
||||||
|
<a class="browser-item sogou" href="http://ie.sogou.com/" target="_blank">
|
||||||
|
<i class="icon-browser"></i>
|
||||||
|
<p class="browser-name">搜狗浏览器</p>
|
||||||
|
</a>
|
||||||
|
<a class="browser-item firefox" href="http://www.firefox.com.cn/?igfox" target="_blank">
|
||||||
|
<i class="icon-browser"></i>
|
||||||
|
<p class="browser-name">Firefox浏览器</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="browser-more">
|
||||||
|
<div class="browser-text">如果你正在使用的是双核浏览器,比如QQ浏览器、搜狗浏览器、猎豹浏览器、世界之窗浏览器、傲游浏览器、360浏览器等,可以使用浏览器的极速模式来继续访问本系统。<a id="access" href="javascript:void(0);">查看详情</a>
|
||||||
|
</div>
|
||||||
|
<div id="tips" class="browser-step" style="display: block;">
|
||||||
|
<ul>
|
||||||
|
<li>方法一,点击浏览器顶部地址栏右侧的浏览器兼容模式图标,<img alt="" src="https://wx.gtimg.com/pay/img/error/ie_s.png">或<img alt="" src="https://wx.gtimg.com/pay/img/error/ie_mode.png">,切换到极速模式
|
||||||
|
<p class="demo"><img alt="" src="https://wx.gtimg.com/pay/img/error/pic_ie01.png"></p>
|
||||||
|
</li>
|
||||||
|
<li>方法二,在当前页面中,点击鼠标右键,选择“切换到极速模式”
|
||||||
|
<p class="demo"><img alt="" src="https://wx.gtimg.com/pay/img/error/pic_ie02.png"></p>
|
||||||
|
</li>
|
||||||
|
<li>方法三,在浏览器菜单栏中选择工具选项,打开“兼容性视图设置”,把设置框底部的“在兼容性视图显示”三个勾选框去掉
|
||||||
|
<p class="demo"><img alt="" src="https://wx.gtimg.com/pay/img/error/pic_ie03.png"></p></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
(function(){
|
||||||
|
var tips = document.getElementById("tips");
|
||||||
|
var access = document.getElementById("access");
|
||||||
|
var isShow = true;
|
||||||
|
access.onclick = function(){
|
||||||
|
if(!isShow){
|
||||||
|
tips.style.display = "block";
|
||||||
|
isShow = true;
|
||||||
|
}else{
|
||||||
|
tips.style.display = "none";
|
||||||
|
isShow = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
31
application/admin/view/index/index.html
Normal file
31
application/admin/view/index/index.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{extend name="layout" /}
|
||||||
|
|
||||||
|
{block name="page-header"}{/block}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
{notempty name="default_pass"}
|
||||||
|
<div class="alert alert-danger alert-dismissable">
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||||
|
<h3 class="font-w300 push-15">安全提示</h3>
|
||||||
|
<p>超级管理员默认密码未修改,建议马上 <a class="alert-link link-effect" href="{:url('user/index/edit', ['id' => 1])}">修改</a>。</p>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
{// 后台首页钩子}
|
||||||
|
<div class="row">
|
||||||
|
{:hook('admin_index')}
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block name="script"}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$.ajax({
|
||||||
|
url: '{:url("checkUpdate")}',
|
||||||
|
type: 'GET'
|
||||||
|
}).done(function(data) {
|
||||||
|
$('#product-auth').html(data.auth);
|
||||||
|
$('#product-update').html($('#product-update').text() + ' ' + data.update);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{/block}
|
493
application/admin/view/layout.html
Normal file
493
application/admin/view/layout.html
Normal file
@ -0,0 +1,493 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--[if IE 9]> <html class="ie9 no-focus" lang="zh"> <![endif]-->
|
||||||
|
<!--[if gt IE 9]><!--> <html class="no-focus" lang="zh"> <!--<![endif]-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
{block name="page-title"}<title>{$page_title|default='后台'} | {:config('web_site_title')} - DolphinPHP</title>{/block}
|
||||||
|
|
||||||
|
<meta name="description" content="{:config('web_site_description')}">
|
||||||
|
<meta name="author" content="caiweiming">
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1.0,user-scalable=0">
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<!-- The following icons can be replaced with your own, they are used by desktop and mobile browsers -->
|
||||||
|
<link rel="shortcut icon" href="__ADMIN_IMG__/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<link rel="icon" type="image/png" href="__ADMIN_IMG__/favicons/favicon-16x16.png" sizes="16x16">
|
||||||
|
<link rel="icon" type="image/png" href="__ADMIN_IMG__/favicons/favicon-32x32.png" sizes="32x32">
|
||||||
|
<link rel="icon" type="image/png" href="__ADMIN_IMG__/favicons/favicon-96x96.png" sizes="96x96">
|
||||||
|
<link rel="icon" type="image/png" href="__ADMIN_IMG__/favicons/favicon-160x160.png" sizes="160x160">
|
||||||
|
<link rel="icon" type="image/png" href="__ADMIN_IMG__/favicons/favicon-192x192.png" sizes="192x192">
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="__ADMIN_IMG__/favicons/apple-touch-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="__ADMIN_IMG__/favicons/apple-touch-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="__ADMIN_IMG__/favicons/apple-touch-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="__ADMIN_IMG__/favicons/apple-touch-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="__ADMIN_IMG__/favicons/apple-touch-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="__ADMIN_IMG__/favicons/apple-touch-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="__ADMIN_IMG__/favicons/apple-touch-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="__ADMIN_IMG__/favicons/apple-touch-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="__ADMIN_IMG__/favicons/apple-touch-icon-180x180.png">
|
||||||
|
<!-- END Icons -->
|
||||||
|
|
||||||
|
<!-- Stylesheets -->
|
||||||
|
<!-- Page JS Plugins CSS -->
|
||||||
|
{notempty name="_css_files"}
|
||||||
|
{eq name="Think.config.minify_status" value="1"}
|
||||||
|
<link rel="stylesheet" href="{:minify('group', $_css_files)}">
|
||||||
|
{else/}
|
||||||
|
{volist name="_css_files" id="css"}
|
||||||
|
{:load_assets($css)}
|
||||||
|
{/volist}
|
||||||
|
{/eq}
|
||||||
|
{/notempty}
|
||||||
|
|
||||||
|
{notempty name="_icons"}
|
||||||
|
{volist name="_icons" id="icon"}
|
||||||
|
<link rel="stylesheet" href="{$icon.url}">
|
||||||
|
{/volist}
|
||||||
|
{/notempty}
|
||||||
|
|
||||||
|
{block name="plugins-css"}{/block}
|
||||||
|
|
||||||
|
<!-- Bootstrap and OneUI CSS framework -->
|
||||||
|
{eq name="Think.config.minify_status" value="1"}
|
||||||
|
<link rel="stylesheet" id="css-main" href="{:minify('group', 'libs_css,core_css')}">
|
||||||
|
{else/}
|
||||||
|
<link rel="stylesheet" href="__LIBS__/sweetalert/sweetalert.min.css?v={:config('asset_version')}">
|
||||||
|
<link rel="stylesheet" href="__LIBS__/magnific-popup/magnific-popup.min.css?v={:config('asset_version')}">
|
||||||
|
<link rel="stylesheet" href="__ADMIN_CSS__/bootstrap.min.css?v={:config('asset_version')}">
|
||||||
|
<link rel="stylesheet" href="__ADMIN_CSS__/oneui.css?v={:config('asset_version')}">
|
||||||
|
<link rel="stylesheet" href="__ADMIN_CSS__/dolphin.css?v={:config('asset_version')}" id="css-main">
|
||||||
|
<link rel="stylesheet" href="__LIBS__/viewer/viewer.min.css?v={:config('asset_version')}">
|
||||||
|
{/eq}
|
||||||
|
<link rel="stylesheet" id="css-theme" href="__ADMIN_CSS__/themes/{:config('system_color')}.min.css?v={:config('asset_version')}">
|
||||||
|
|
||||||
|
<!--页面css-->
|
||||||
|
{block name="style"}{/block}
|
||||||
|
{notempty name="_pop"}
|
||||||
|
<style>
|
||||||
|
#page-container.sidebar-l.sidebar-o {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
.header-navbar-fixed #main-container {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{/notempty}
|
||||||
|
<!-- END Stylesheets -->
|
||||||
|
|
||||||
|
<!--插件css钩子-->
|
||||||
|
{:hook('page_plugin_css')}
|
||||||
|
|
||||||
|
<!--自定义css-->
|
||||||
|
<link rel="stylesheet" href="__ADMIN_CSS__/custom.css?v={:config('asset_version')}">
|
||||||
|
<script>
|
||||||
|
// url
|
||||||
|
var dolphin = {
|
||||||
|
'top_menu_url': '{:url("admin/ajax/getSidebarMenu")}',
|
||||||
|
'theme_url': '{:url("admin/ajax/setTheme")}',
|
||||||
|
'jcrop_upload_url': '{$jcrop_upload_url ? $jcrop_upload_url : url("admin/attachment/upload", ["dir" => "images", "from" => "jcrop", "module" => request()->module()])}',
|
||||||
|
'editormd_upload_url': '{$editormd_upload_url ? $editormd_upload_url : url("admin/attachment/upload", ["dir" => "images", "from" => "editormd", "module" => request()->module()])}',
|
||||||
|
'editormd_mudule_path': '__LIBS__/editormd/lib/',
|
||||||
|
'ueditor_upload_url': '{$ueditor_upload_url ? $ueditor_upload_url : url("admin/attachment/upload", ["dir" => "images", "from" => "ueditor", "module" => request()->module()])}',
|
||||||
|
'wangeditor_upload_url': '{$wangeditor_upload_url ? $wangeditor_upload_url : url("admin/attachment/upload", ["dir" => "images", "from" => "wangeditor", "module" => request()->module()])}',
|
||||||
|
'wangeditor_emotions': "__LIBS__/wang-editor/emotions.data",
|
||||||
|
'ckeditor_img_upload_url': '{$ckeditor_img_upload_url ? $ckeditor_img_upload_url : url("admin/attachment/upload", ["dir" => "images", "from" => "ckeditor", "module" => request()->module()])}',
|
||||||
|
'WebUploader_swf': '__LIBS__/webuploader/Uploader.swf',
|
||||||
|
'file_upload_url': '{$file_upload_url ? $file_upload_url : url("admin/attachment/upload", ["dir" => "files", "module" => request()->module()])}',
|
||||||
|
'image_upload_url': '{$image_upload_url ? $image_upload_url : url("admin/attachment/upload", ["dir" => "images", "module" => request()->module()])}',
|
||||||
|
'upload_check_url': '{$upload_check_url ? $upload_check_url : url("admin/ajax/check")}',
|
||||||
|
'get_level_data': '{:url("admin/ajax/getLevelData")}',
|
||||||
|
'quick_edit_url': '{$quick_edit_url ? $quick_edit_url : url("quickEdit")}',
|
||||||
|
'aside_edit_url': '{$aside_edit_url ? $aside_edit_url : url("admin/system/quickEdit")}',
|
||||||
|
'triggers': {:json_encode(isset($field_triggers) ? $field_triggers : [])}, // 触发器集合
|
||||||
|
'field_hide': '{$field_hide|default=""}', // 需要隐藏的字段
|
||||||
|
'field_values': '{$field_values|default=""}',
|
||||||
|
'validate': '{$validate|default=""}', // 验证器
|
||||||
|
'validate_fields': '{$validate_fields|default=""}', // 验证字段
|
||||||
|
'search_field': '{:input("param.search_field", "")}', // 搜索字段
|
||||||
|
// 字段过滤
|
||||||
|
'_filter': '{$Request.param._filter ? $Request.param._filter : (isset($_filter) ? $_filter : "")}',
|
||||||
|
'_filter_content': '{$Request.param._filter_content == '' ? (isset($_filter_content) ? $_filter_content : "") : $Request.param._filter_content}',
|
||||||
|
'_field_display': '{$Request.param._field_display ? $Request.param._field_display : (isset($_field_display) ? $_field_display : "")}',
|
||||||
|
'_field_clear': {:json_encode(isset($field_clear) ? $field_clear : [])},
|
||||||
|
'get_filter_list': '{:url("admin/ajax/getFilterList")}',
|
||||||
|
'curr_url': '{:url("", $Request.route)}',
|
||||||
|
'curr_params': {:json_encode($Request.param)},
|
||||||
|
'layer': {:json_encode(config("zbuilder.pop"))}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Page Container -->
|
||||||
|
<div id="page-container" class="sidebar-l sidebar-o side-scroll header-navbar-fixed {empty name="_pop"}{$_COOKIE['sidebarMini'] ?= 'sidebar-mini'}{/empty}">
|
||||||
|
<!-- Side Overlay-->
|
||||||
|
{empty name="_pop"}
|
||||||
|
{block name="aside"}
|
||||||
|
<aside id="side-overlay">
|
||||||
|
<!-- Side Overlay Scroll Container -->
|
||||||
|
<div id="side-overlay-scroll">
|
||||||
|
<!-- Side Header -->
|
||||||
|
<div class="side-header side-content">
|
||||||
|
<!-- Layout API, functionality initialized in App() -> uiLayoutApi() -->
|
||||||
|
<button class="btn btn-default pull-right" type="button" data-toggle="layout" data-action="side_overlay_close">
|
||||||
|
<i class="fa fa-times"></i>
|
||||||
|
</button>
|
||||||
|
<span>
|
||||||
|
<img class="img-avatar img-avatar32" src="{$Think.session.user_auth.uid|get_avatar}" alt="">
|
||||||
|
<span class="font-w600 push-10-l">{:session('user_auth.username')}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- END Side Header -->
|
||||||
|
<!--侧栏-->
|
||||||
|
{include file="../application/common/builder/aside/layout.html" /}
|
||||||
|
</div>
|
||||||
|
<!-- END Side Overlay Scroll Container -->
|
||||||
|
</aside>
|
||||||
|
{/block}
|
||||||
|
{/empty}
|
||||||
|
<!-- END Side Overlay -->
|
||||||
|
|
||||||
|
<!-- Sidebar -->
|
||||||
|
{empty name="_pop"}
|
||||||
|
{block name="sidebar"}
|
||||||
|
<nav id="sidebar">
|
||||||
|
<!-- Sidebar Scroll Container -->
|
||||||
|
<div id="sidebar-scroll">
|
||||||
|
<!-- Sidebar Content -->
|
||||||
|
<!-- Adding .sidebar-mini-hide to an element will hide it when the sidebar is in mini mode -->
|
||||||
|
<div class="sidebar-content">
|
||||||
|
<!-- Side Header -->
|
||||||
|
<div class="side-header side-content bg-white-op dolphin-header">
|
||||||
|
<!-- Layout API, functionality initialized in App() -> uiLayoutApi() -->
|
||||||
|
<button class="btn btn-link text-gray pull-right hidden-md hidden-lg" type="button" data-toggle="layout" data-action="sidebar_close">
|
||||||
|
<i class="fa fa-times"></i>
|
||||||
|
</button>
|
||||||
|
<!-- Themes functionality initialized in App() -> uiHandleTheme() -->
|
||||||
|
<div class="btn-group pull-right">
|
||||||
|
<button class="btn btn-link text-gray dropdown-toggle" data-toggle="dropdown" type="button">
|
||||||
|
<i class="si si-drop"></i>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right font-s13 sidebar-mini-hide">
|
||||||
|
<li {$system_color == 'modern' ?= 'class="active"'}>
|
||||||
|
<a data-toggle="theme" data-theme="modern" data-css="__ADMIN_CSS__/themes/modern.min.css" tabindex="-1" href="javascript:void(0)">
|
||||||
|
<i class="fa fa-circle text-modern pull-right"></i> <span class="font-w600">Modern</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li {$system_color == 'amethyst' ?= 'class="active"'}>
|
||||||
|
<a data-toggle="theme" data-theme="amethyst" data-css="__ADMIN_CSS__/themes/amethyst.min.css" tabindex="-1" href="javascript:void(0)">
|
||||||
|
<i class="fa fa-circle text-amethyst pull-right"></i> <span class="font-w600">Amethyst</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li {$system_color == 'city' ?= 'class="active"'}>
|
||||||
|
<a data-toggle="theme" data-theme="city" data-css="__ADMIN_CSS__/themes/city.min.css" tabindex="-1" href="javascript:void(0)">
|
||||||
|
<i class="fa fa-circle text-city pull-right"></i> <span class="font-w600">City</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li {$system_color == 'flat' ?= 'class="active"'}>
|
||||||
|
<a data-toggle="theme" data-theme="flat" data-css="__ADMIN_CSS__/themes/flat.min.css" tabindex="-1" href="javascript:void(0)">
|
||||||
|
<i class="fa fa-circle text-flat pull-right"></i> <span class="font-w600">Flat</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li {$system_color == 'smooth' ?= 'class="active"'}>
|
||||||
|
<a data-toggle="theme" data-theme="smooth" data-css="__ADMIN_CSS__/themes/smooth.min.css" tabindex="-1" href="javascript:void(0)">
|
||||||
|
<i class="fa fa-circle text-smooth pull-right"></i> <span class="font-w600">Smooth</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li {$system_color == 'default' ?= 'class="active"'}>
|
||||||
|
<a data-toggle="theme" data-theme="default" tabindex="-1" href="javascript:void(0)">
|
||||||
|
<i class="fa fa-circle text-default pull-right"></i> <span class="font-w600">Default</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<a class="h5 text-white" href="{:url('admin/index/index')}">
|
||||||
|
{notempty name="Think.config.web_site_logo"}
|
||||||
|
<img src="{$Think.config.web_site_logo|get_file_path}" class="logo" alt="{$Think.config.web_site_title|default='Dolphin PHP'}">
|
||||||
|
{else/}
|
||||||
|
<img src="{$Think.config.public_static_path}admin/img/logo.png" class="logo" alt="Dolphin PHP">
|
||||||
|
{/notempty}
|
||||||
|
|
||||||
|
{notempty name="Think.config.web_site_logo_text"}
|
||||||
|
<img src="{$Think.config.web_site_logo_text|get_file_path}" class="logo-text sidebar-mini-hide" alt="{$Think.config.web_site_title|default='Dolphin PHP'}">
|
||||||
|
{else/}
|
||||||
|
<img src="{$Think.config.public_static_path}admin/img/logo-text.png" class="logo-text sidebar-mini-hide" alt="Dolphin PHP">
|
||||||
|
{/notempty}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<!-- END Side Header -->
|
||||||
|
|
||||||
|
<!-- Side Content -->
|
||||||
|
<div class="side-content" id="sidebar-menu">
|
||||||
|
{notempty name="_sidebar_menus"}
|
||||||
|
<ul class="nav-main" id="nav-{$_location[0]['id']}">
|
||||||
|
{volist name="_sidebar_menus" id="menu"}
|
||||||
|
<li {$menu['id'] == $_location[1]["id"]?='class="open"'}>
|
||||||
|
{notempty name="menu.url_value"}
|
||||||
|
<a {if($menu['id'] == $_location[1]["id"])}class="active"{/if} href="{$menu.url_value}" target="{$menu.url_target}"><i class="{$menu.icon}"></i><span class="sidebar-mini-hide">{$menu.title}</span></a>
|
||||||
|
{else/}
|
||||||
|
<a class="nav-submenu" data-toggle="nav-submenu" href="javascript:void(0);"><i class="{$menu.icon}"></i><span class="sidebar-mini-hide">{$menu.title}</span></a>
|
||||||
|
{notempty name="menu['child']"}
|
||||||
|
<ul>
|
||||||
|
{volist name="menu['child']" id="submenu"}
|
||||||
|
<li>
|
||||||
|
<a {if(isset($_location[2]) && $submenu['id'] == $_location[2]["id"])}class="active"{/if} href="{$submenu.url_value}" target="{$submenu.url_target}"><i class="{$submenu.icon}"></i>{$submenu.title}</a>
|
||||||
|
</li>
|
||||||
|
{/volist}
|
||||||
|
</ul>
|
||||||
|
{/notempty}
|
||||||
|
{/notempty}
|
||||||
|
</li>
|
||||||
|
{/volist}
|
||||||
|
</ul>
|
||||||
|
{/notempty}
|
||||||
|
</div>
|
||||||
|
<!-- END Side Content -->
|
||||||
|
</div>
|
||||||
|
<!-- Sidebar Content -->
|
||||||
|
</div>
|
||||||
|
<!-- END Sidebar Scroll Container -->
|
||||||
|
</nav>
|
||||||
|
{/block}
|
||||||
|
{/empty}
|
||||||
|
<!-- END Sidebar -->
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
{empty name="_pop"}
|
||||||
|
{block name="header"}
|
||||||
|
<header id="header-navbar" class="content-mini content-mini-full">
|
||||||
|
<!-- Header Navigation Right -->
|
||||||
|
<ul class="nav-header pull-right">
|
||||||
|
<li>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-default btn-image dropdown-toggle" data-toggle="dropdown" type="button">
|
||||||
|
<img src="{$Think.session.user_auth.uid|get_avatar}" alt="{:session('user_auth.username')}">
|
||||||
|
<span class="caret"></span>
|
||||||
|
{notempty name="_message"}
|
||||||
|
{gt name="_message" value="0"}
|
||||||
|
<i class="fa fa-circle text-danger notice-circle"></i>
|
||||||
|
{/gt}
|
||||||
|
{/notempty}
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right">
|
||||||
|
<li class="dropdown-header">{:session('user_auth.username')} ({:session('user_auth.role_name')})</li>
|
||||||
|
<li>
|
||||||
|
<a tabindex="-1" href="{:url('admin/index/profile')}">
|
||||||
|
<i class="si si-settings pull-right"></i>个人设置
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a tabindex="-1" href="{:url('admin/message/index')}">
|
||||||
|
<i class="si si-envelope-open pull-right"></i><span class="badge badge-primary pull-right">{$_message|default=0}</span>消息中心
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li>
|
||||||
|
<a tabindex="-1" href="{:url('user/publics/signout')}">
|
||||||
|
<i class="si si-logout pull-right"></i>退出帐号
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="btn btn-default ajax-get" href="{:url('admin/index/wipeCache')}" data-toggle="tooltip" data-placement="bottom" data-original-title="清空缓存">
|
||||||
|
<i class="fa fa-trash"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="btn btn-default" href="{:rtrim(home_url('/'), '/')}" target="_blank" data-toggle="tooltip" data-placement="bottom" data-original-title="打开前台">
|
||||||
|
<i class="fa fa-external-link-square"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<!-- Layout API, functionality initialized in App() -> uiLayoutApi() -->
|
||||||
|
<button class="btn btn-default" data-toggle="layout" data-action="side_overlay_toggle" title="侧边栏" type="button">
|
||||||
|
<i class="fa fa-tasks"></i>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<!-- END Header Navigation Right -->
|
||||||
|
|
||||||
|
<!-- Header Navigation Left -->
|
||||||
|
<ul class="nav nav-pills pull-left">
|
||||||
|
<li class="hidden-md hidden-lg">
|
||||||
|
<!-- Layout API, functionality initialized in App() -> uiLayoutApi() -->
|
||||||
|
<a href="javascript:void(0)" data-toggle="layout" data-action="sidebar_toggle"><i class="fa fa-navicon"></i></a>
|
||||||
|
</li>
|
||||||
|
<li class="hidden-xs hidden-sm">
|
||||||
|
<!-- Layout API, functionality initialized in App() -> uiLayoutApi() -->
|
||||||
|
<a href="javascript:void(0)" title="打开/关闭左侧导航" data-toggle="layout" data-action="sidebar_mini_toggle"><i class="fa fa-bars"></i></a>
|
||||||
|
</li>
|
||||||
|
{notempty name="_top_menus"}
|
||||||
|
{volist name="_top_menus" id="menu"}
|
||||||
|
<li class="hidden-xs hidden-sm {$menu['id'] == $_location[0]['id'] ?= 'active'}">
|
||||||
|
{in name="menu.url_type" value="module_admin,module_home"}
|
||||||
|
<a href="javascript:void(0);" data-module-id="{$menu['id']}" data-module="{$menu['module']}" data-controller="{$menu['controller']}" target="{$menu['url_target']}" class="top-menu"><i class="{$menu.icon}"></i> {$menu.title}</a>
|
||||||
|
{else/}
|
||||||
|
<a href="{$menu['url_value']}" target="{$menu['url_target']}"><i class="{$menu.icon}"></i> {$menu.title}</a>
|
||||||
|
{/in}
|
||||||
|
</li>
|
||||||
|
{/volist}
|
||||||
|
{/notempty}
|
||||||
|
<li>
|
||||||
|
<!-- Opens the Apps modal found at the bottom of the page, before including JS code -->
|
||||||
|
<a href="#" data-toggle="modal" data-target="#apps-modal"><i class="si si-grid"></i></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<!-- END Header Navigation Left -->
|
||||||
|
</header>
|
||||||
|
{/block}
|
||||||
|
{/empty}
|
||||||
|
<!-- END Header -->
|
||||||
|
|
||||||
|
<!-- Main Container -->
|
||||||
|
<main id="main-container">
|
||||||
|
<!-- Page Header -->
|
||||||
|
{block name="page-header"}
|
||||||
|
{empty name="_pop"}
|
||||||
|
<div class="bg-gray-lighter">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><i class="fa fa-map-marker"></i></li>
|
||||||
|
{notempty name="_location"}
|
||||||
|
{volist name="_location" id="v"}
|
||||||
|
<li><a class="link-effect" href="{notempty name='$v["url_value"]'}{:url($v.url_value, $v.params)}{else/}javascript:void(0);{/notempty}">{$v.title}</a></li>
|
||||||
|
{/volist}
|
||||||
|
{/notempty}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
{/empty}
|
||||||
|
{/block}
|
||||||
|
<!-- END Page Header -->
|
||||||
|
|
||||||
|
<!-- Page Content -->
|
||||||
|
<div class="content">
|
||||||
|
{// 页面提示钩子}
|
||||||
|
{:hook('page_tips')}
|
||||||
|
{// 主体内容}
|
||||||
|
{block name="content"}{/block}
|
||||||
|
</div>
|
||||||
|
<!-- END Page Content -->
|
||||||
|
</main>
|
||||||
|
<!-- END Main Container -->
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
{empty name="_pop"}
|
||||||
|
<footer id="page-footer" class="content-mini content-mini-full font-s12 bg-gray-lighter clearfix">
|
||||||
|
<div class="pull-right">
|
||||||
|
Crafted with <i class="fa fa-heart text-city"></i> by <a class="font-w600" href="{:config('dolphin.company_website')}" target="_blank">{:config('dolphin.company_name')}</a>
|
||||||
|
</div>
|
||||||
|
<div class="pull-left">
|
||||||
|
<a class="font-w600" href="{:config('dolphin.product_website')}" target="_blank">{:config('dolphin.product_name')} {:config('dolphin.product_version')}</a> © <span class="js-year-copy"></span>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
{/empty}
|
||||||
|
<!-- END Footer -->
|
||||||
|
</div>
|
||||||
|
<!-- END Page Container -->
|
||||||
|
|
||||||
|
<!-- Apps Modal -->
|
||||||
|
<!-- Opens from the button in the header -->
|
||||||
|
<div class="modal fade" id="apps-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-top">
|
||||||
|
<div class="modal-content">
|
||||||
|
<!-- Apps Block -->
|
||||||
|
<div class="block block-themed block-transparent">
|
||||||
|
<div class="block-header bg-primary-dark">
|
||||||
|
<ul class="block-options">
|
||||||
|
<li>
|
||||||
|
<button data-dismiss="modal" type="button"><i class="si si-close"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="block-title">所有模块</h3>
|
||||||
|
</div>
|
||||||
|
<div class="block-content">
|
||||||
|
<div class="row text-center">
|
||||||
|
{notempty name="_top_menus_all"}
|
||||||
|
{volist name="_top_menus_all" id="menu"}
|
||||||
|
<div class="col-xs-6 col-sm-3">
|
||||||
|
{in name="menu.url_type" value="module_admin,module_home"}
|
||||||
|
<a class="block block-rounded top-menu" href="javascript:void(0);" data-module-id="{$menu['id']}" data-module="{$menu['module']}" data-controller="{$menu['controller']}" target="{$menu['url_target']}">
|
||||||
|
<div class="block-content text-white {$menu['id'] == $_location[0]['id'] ? 'bg-primary' : 'bg-primary-dark'}">
|
||||||
|
<i class="{$menu.icon} fa-2x"></i>
|
||||||
|
<div class="font-w600 push-15-t push-15">{$menu.title}</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{else/}
|
||||||
|
<a class="block block-rounded" href="{$menu['url_value']}" target="{$menu['url_target']}">
|
||||||
|
<div class="block-content text-white {$menu['id'] == $_location[0]['id'] ? 'bg-primary' : 'bg-primary-dark'}">
|
||||||
|
<i class="{$menu.icon} fa-2x"></i>
|
||||||
|
<div class="font-w600 push-15-t push-15">{$menu.title}</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{/in}
|
||||||
|
</div>
|
||||||
|
{/volist}
|
||||||
|
{/notempty}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- END Apps Block -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- END Apps Modal -->
|
||||||
|
<!-- OneUI Core JS: jQuery, Bootstrap, slimScroll, scrollLock, Appear, CountTo, Placeholder, Cookie and App.js -->
|
||||||
|
{eq name="Think.config.minify_status" value="1"}
|
||||||
|
<script src="{:minify('group', 'core_js,libs_js')}"></script>
|
||||||
|
{else/}
|
||||||
|
<script src="__ADMIN_JS__/core/jquery.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/core/bootstrap.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/core/jquery.slimscroll.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/core/jquery.scrollLock.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/core/jquery.appear.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/core/jquery.countTo.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/core/jquery.placeholder.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/core/js.cookie.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__LIBS__/magnific-popup/magnific-popup.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/app.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/dolphin.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/builder/form.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/builder/aside.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__ADMIN_JS__/builder/table.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__LIBS__/bootstrap-notify/bootstrap-notify.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__LIBS__/sweetalert/sweetalert.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__LIBS__/js-xss/xss.min.js?v={:config('asset_version')}"></script>
|
||||||
|
<script src="__LIBS__/viewer/viewer.min.js?v={:config('asset_version')}"></script>
|
||||||
|
{/eq}
|
||||||
|
|
||||||
|
<!-- Page JS Plugins -->
|
||||||
|
<script src="__LIBS__/layer/layer.js?v={:config('asset_version')}"></script>
|
||||||
|
{notempty name="_js_files"}
|
||||||
|
{eq name="Think.config.minify_status" value="1"}
|
||||||
|
<script src="{:minify('group', $_js_files)}"></script>
|
||||||
|
{else/}
|
||||||
|
{volist name="_js_files" id="js"}
|
||||||
|
{:load_assets($js, 'js')}
|
||||||
|
{/volist}
|
||||||
|
{/eq}
|
||||||
|
{/notempty}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
jQuery(function () {
|
||||||
|
App.initHelpers(['appear', 'slimscroll', 'magnific-popup', 'table-tools']);
|
||||||
|
{notempty name="_js_init"}
|
||||||
|
App.initHelpers({$_js_init|raw});
|
||||||
|
{/notempty}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--页面js-->
|
||||||
|
{block name="script"}{/block}
|
||||||
|
|
||||||
|
<!--插件js钩子-->
|
||||||
|
{:hook('page_plugin_js')}
|
||||||
|
|
||||||
|
{// 额外HTML代码 }
|
||||||
|
{$extra_html|raw|default=''}
|
||||||
|
</body>
|
||||||
|
</html>
|
203
application/admin/view/menu/index.html
Normal file
203
application/admin/view/menu/index.html
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
{extend name="layout" /}
|
||||||
|
|
||||||
|
{block name="plugins-css"}
|
||||||
|
<link href="__LIBS__/jquery-nestable/jquery.nestable.css" rel="stylesheet" type="text/css" />
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
<div class="alert alert-warning alert-dismissable">
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||||
|
<p><strong><i class="fa fa-fw fa-info-circle"></i> 提示:</strong>按住表头可拖动节点,调整后点击【保存节点】。</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="block">
|
||||||
|
{notempty name="tab_nav"}
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
{volist name="tab_nav['tab_list']" id="tab"}
|
||||||
|
<li {eq name="tab_nav.curr_tab" value="$key"}class="active"{/eq}>
|
||||||
|
<a href="{$tab.url}">{$tab.title}</a>
|
||||||
|
</li>
|
||||||
|
{/volist}
|
||||||
|
<li {eq name="tab_nav.curr_tab" value="module-sort"}class="active"{/eq}>
|
||||||
|
<a href="{:url('', ['group' => 'module-sort'])}">模块排序</a>
|
||||||
|
</li>
|
||||||
|
<li class="pull-right">
|
||||||
|
<ul class="block-options push-10-t push-10-r">
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="refresh_toggle" data-action-mode="demo"><i class="si si-refresh"></i></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="content_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="close"><i class="si si-close"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{else/}
|
||||||
|
<div class="block-header bg-gray-lighter">
|
||||||
|
<ul class="block-options">
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="refresh_toggle" data-action-mode="demo"><i class="si si-refresh"></i></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="content_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="close"><i class="si si-close"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="block-title">{$page_title|raw}</h3>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
<div class="block-content tab-content">
|
||||||
|
<div class="tab-pane active">
|
||||||
|
{notempty name="menus"}
|
||||||
|
<div class="row data-table-toolbar">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<form action="{$Request.url}" method="get">
|
||||||
|
<div class="toolbar-btn-action">
|
||||||
|
<a title="新增" class="btn btn-primary" href="{:url('add', ['module' => $Request.param.group])}"><i class="fa fa-plus-circle"></i> 新增</a>
|
||||||
|
<button title="保存" type="button" class="btn btn-default disabled" id="save" disabled><i class="fa fa-check-circle-o"></i> 保存节点</button>
|
||||||
|
<button title="隐藏禁用节点" type="button" class="btn btn-danger" id="hide_disable"><i class="fa fa-eye-slash"></i> 隐藏禁用节点</button>
|
||||||
|
<button title="显示禁用节点" type="button" class="btn btn-info" id="show_disable"><i class="fa fa-eye"></i> 显示禁用节点</button>
|
||||||
|
<button title="展开所有节点" type="button" class="btn btn-success" id="expand-all"><i class="fa fa-plus"></i> 展开所有节点</button>
|
||||||
|
<button title="收起所有节点" type="button" class="btn btn-warning" id="collapse-all"><i class="fa fa-minus"></i> 收起所有节点</button>
|
||||||
|
<span class="form-inline">
|
||||||
|
<input class="form-control" type="text" name="max" value="{$Request.get.max|default=''}" placeholder="显示层数">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dd" id="menu_list">
|
||||||
|
<ol class="dd-list">{$menus|raw}</ol>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
|
||||||
|
{notempty name="modules"}
|
||||||
|
<form action="{:url('')}" method="post" name="sort-form" class="sort-form">
|
||||||
|
<button title="保存" type="submit" class="btn btn-success push-10 ajax-post" target-form="sort-form">保存排序</button>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div id="sortable" class="connectedSortable push-20">
|
||||||
|
{volist name="modules" id="module"}
|
||||||
|
<div class="sortable-item pull-left">
|
||||||
|
<input type="hidden" name="sort[]" value="{$key}">
|
||||||
|
<i class="{$module.icon}"></i> {$module.title}
|
||||||
|
</div>
|
||||||
|
{/volist}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{/notempty}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block name="script"}
|
||||||
|
<script src="__LIBS__/jquery-nestable/jquery.nestable.js"></script>
|
||||||
|
<script src="__LIBS__/jquery-ui/jquery-ui.min.js"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
// 模块拖拽
|
||||||
|
$( "#sortable" ).sortable({
|
||||||
|
connectWith: ".connectedSortable"
|
||||||
|
}).disableSelection();
|
||||||
|
|
||||||
|
// 保存节点
|
||||||
|
$('#save').click(function(){
|
||||||
|
Dolphin.loading();
|
||||||
|
$.post("{:url('save')}", {menus: $('#menu_list').nestable('serialize')}, function(data) {
|
||||||
|
Dolphin.loading('hide');
|
||||||
|
if (data.code) {
|
||||||
|
$('#save').removeClass('btn-success').addClass('btn-default disabled');
|
||||||
|
Dolphin.notify(data.msg, 'success');
|
||||||
|
} else {
|
||||||
|
Dolphin.notify(data.msg, 'danger');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化节点拖拽
|
||||||
|
$('#menu_list').nestable({maxDepth:4}).on('change', function(){
|
||||||
|
$('#save').removeAttr("disabled").removeClass('btn-default disabled').addClass('btn-success');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 隐藏禁用节点
|
||||||
|
$('#hide_disable').click(function(){
|
||||||
|
$('.dd-disable').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 显示禁用节点
|
||||||
|
$('#show_disable').click(function(){
|
||||||
|
$('.dd-disable').show();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 展开所有节点
|
||||||
|
$('#expand-all').click(function(){
|
||||||
|
$('#menu_list').nestable('expandAll');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 收起所有节点
|
||||||
|
$('#collapse-all').click(function(){
|
||||||
|
$('#menu_list').nestable('collapseAll');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 禁用节点
|
||||||
|
$('.dd3-content').delegate('.disable', 'click', function(){
|
||||||
|
var self = $(this);
|
||||||
|
var ids = self.data('ids');
|
||||||
|
var ajax_url = '{:url("disable", ["table" => "admin_menu"])}';
|
||||||
|
Dolphin.loading();
|
||||||
|
$.post(ajax_url, {ids:ids}, function(data) {
|
||||||
|
Dolphin.loading('hide');
|
||||||
|
if (data.code) {
|
||||||
|
self.attr('data-original-title', '启用').removeClass('disable').addClass('enable')
|
||||||
|
.children().removeClass('fa-ban').addClass('fa-check-circle-o')
|
||||||
|
.closest('.dd-item')
|
||||||
|
.addClass('dd-disable');
|
||||||
|
} else {
|
||||||
|
Dolphin.notify(data.msg, 'danger');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 启用节点
|
||||||
|
$('.dd3-content').delegate('.enable', 'click', function(){
|
||||||
|
var self = $(this);
|
||||||
|
var ids = self.data('ids');
|
||||||
|
var ajax_url = '{:url("enable", ["table" => "admin_menu"])}';
|
||||||
|
Dolphin.loading();
|
||||||
|
$.post(ajax_url, {ids:ids}, function(data) {
|
||||||
|
Dolphin.loading('hide');
|
||||||
|
if (data.code) {
|
||||||
|
self.attr('data-original-title', '禁用').removeClass('enable').addClass('disable')
|
||||||
|
.children().removeClass('fa-check-circle-o').addClass('fa-ban')
|
||||||
|
.closest('.dd-item')
|
||||||
|
.removeClass('dd-disable');
|
||||||
|
} else {
|
||||||
|
Dolphin.notify(data.msg, 'danger');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{/block}
|
63
application/admin/view/module/export.html
Normal file
63
application/admin/view/module/export.html
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
{extend name="layout" /}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="block">
|
||||||
|
<div class="block-header bg-gray-lighter">
|
||||||
|
<ul class="block-options">
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="refresh_toggle" data-action-mode="demo"><i class="si si-refresh"></i></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="content_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="close"><i class="si si-close"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="block-title">{$page_title|default=""}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block-content tab-content">
|
||||||
|
<div class="tab-pane active">
|
||||||
|
<div class="block-content">
|
||||||
|
<form class="form-horizontal form-builder" action="{:url('export')}" method="get">
|
||||||
|
<input type="hidden" name="name" value="{$Request.param.name|default=''}">
|
||||||
|
<div class="form-group " id="form_group_group">
|
||||||
|
<h4 class="col-xs-12 push-10">是否导出数据</h4>
|
||||||
|
<div class="col-xs-9">
|
||||||
|
<label class="css-input css-radio css-radio-primary css-radio-sm push-10-r">
|
||||||
|
<input type="radio" name="export_data" id="clear1" value="0">
|
||||||
|
<span></span> 否
|
||||||
|
</label>
|
||||||
|
<label class="css-input css-radio css-radio-primary css-radio-sm push-10-r">
|
||||||
|
<input type="radio" name="export_data" id="clear2" value="1" checked="">
|
||||||
|
<span></span> 是
|
||||||
|
</label>
|
||||||
|
<div class="help-block">
|
||||||
|
选择“否”,只导出数据表结构。选择“是”,导出该模块的所有数据
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-minw btn-primary" type="submit" id="uninstall">
|
||||||
|
导出
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-default" type="button" onclick="javascript:history.back(-1);return false;">
|
||||||
|
返回
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
163
application/admin/view/module/index.html
Normal file
163
application/admin/view/module/index.html
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
{extend name="layout" /}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="block">
|
||||||
|
{notempty name="tab_nav"}
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
{volist name="tab_nav['tab_list']" id="tab"}
|
||||||
|
<li {eq name="tab_nav.curr_tab" value="$key"}class="active"{/eq}>
|
||||||
|
<a href="{$tab.url}">{$tab.title}</a>
|
||||||
|
</li>
|
||||||
|
{/volist}
|
||||||
|
<li class="pull-right">
|
||||||
|
<ul class="block-options push-10-t push-10-r">
|
||||||
|
<li>
|
||||||
|
<a href="{:url('index', ['type' => $type])}"><i class="si si-{$type=='list' ? 'list' : 'grid'}"></i></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{else/}
|
||||||
|
<div class="block-header bg-gray-lighter">
|
||||||
|
<ul class="block-options">
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="refresh_toggle" data-action-mode="demo"><i class="si si-refresh"></i></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="content_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="close"><i class="si si-close"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="block-title">{$page_title}</h3>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
<div class="block-content tab-content">
|
||||||
|
<div class="tab-pane active">
|
||||||
|
<div class="row push-20">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="pull-right search-bar">
|
||||||
|
<form class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
||||||
|
<input type="text" class="form-control" value="{:input('get.keyword')}" name="keyword" placeholder="请输入标识/名称/作者">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="toolbar-btn-action">
|
||||||
|
<a title="全部" class="btn btn-default" href="{:url('index')}">全部({$total.all|default='0'})</a>
|
||||||
|
<a title="已启用" class="btn btn-success" href="{:url('index', ['status' => '1'])}">已启用({$total['1']|default='0'})</a>
|
||||||
|
<a title="已禁用" class="btn btn-warning" href="{:url('index', ['status' => '0'])}">已禁用({$total['0']|default='0'})</a>
|
||||||
|
<a title="未安装" class="btn btn-info" href="{:url('index', ['status' => '-1'])}">未安装({$total['-1']|default='0'})</a>
|
||||||
|
<a title="已损坏" class="btn btn-danger" href="{:url('index', ['status' => '-2'])}" id="hide_disable">已损坏({$total['-2']|default='0'})</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row module-list push-20">
|
||||||
|
{empty name="modules"}
|
||||||
|
<div class="table-empty">
|
||||||
|
<div class="text-center empty-info">
|
||||||
|
<i class="fa fa-database"></i> 暂无数据<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/empty}
|
||||||
|
{eq name="type" value="block"}
|
||||||
|
{volist name="modules" id="module"}
|
||||||
|
<div class="col-sm-6 col-md-4 col-lg-3">
|
||||||
|
<div class="block block-rounded">
|
||||||
|
<div class="block-content block-content-full text-center bg-{$module.bg_color|default='danger'} ribbon ribbon-bookmark ribbon-crystal">
|
||||||
|
<div class="ribbon-box font-w600">{$module.version|default='无版本号'}</div>
|
||||||
|
<div class="item item-2x item-circle bg-crystal-op push-20-t push-20 visibility-hidden" data-toggle="appear" data-offset="50" data-class="animated fadeIn">
|
||||||
|
<i class="{$module.icon|default='fa fa-puzzle-piece'} text-white-op"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="h4 text-white">{$module.title|default='无模块标题'}</h3>
|
||||||
|
<div class="text-white-op">
|
||||||
|
<em>{$module.name|default=''}</em>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="block-content bg-gray-lighter">
|
||||||
|
<div class="{$module.status_class} pull-right push-10-l">{$module.status_info|raw}</div>
|
||||||
|
<div class="push-10">
|
||||||
|
<a class="h5" href="{$module.author_url|default=''}" target="_blank"><i class="fa fa-user"></i> {$module.author|default=''}</a>
|
||||||
|
</div>
|
||||||
|
<div class="push-10 mheight-100">
|
||||||
|
<div data-toggle="slimscroll" data-height="110px">
|
||||||
|
<p class="text-gray-dark">{$module.description|raw|default='暂无简介'}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center push">
|
||||||
|
{$module.actions|raw}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/volist}
|
||||||
|
{else/}
|
||||||
|
{notempty name="modules"}
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="builder-table-wrapper" id="builder-table-wrapper">
|
||||||
|
<div class="builder-table" id="builder-table">
|
||||||
|
<table class="table table-builder table-hover table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>名称</th>
|
||||||
|
<th>图标</th>
|
||||||
|
<th>版本</th>
|
||||||
|
<th>作者</th>
|
||||||
|
<th>简介</th>
|
||||||
|
<th class="column-right_button">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{volist name="modules" id="module"}
|
||||||
|
<tr>
|
||||||
|
<td>{$module.title|default='无模块标题'}</td>
|
||||||
|
<td><i class="{$module.icon|default='fa fa-puzzle-piece'}"></i></td>
|
||||||
|
<td>{$module.version|default='无版本号'}</td>
|
||||||
|
<td><a href="{$module.author_url|default=''}" target="_blank">{$module.author|default=''}</a></td>
|
||||||
|
<td>{$module.description|raw|default='暂无简介'}</td>
|
||||||
|
<td>{$module.actions|raw}</td>
|
||||||
|
</tr>
|
||||||
|
{/volist}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
{/eq}
|
||||||
|
</div>
|
||||||
|
<div class="data-table-toolbar">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
{// 分页 }
|
||||||
|
{notempty name="pages"}
|
||||||
|
{$pages}
|
||||||
|
{/notempty}
|
||||||
|
{notempty name="row_list"}
|
||||||
|
<div class="pagination-info pull-right">
|
||||||
|
<form action="" method="get">
|
||||||
|
<input type="text" class="form-control input-sm go-page" name="page" value="{:input('param.page', '1')}">
|
||||||
|
<input type="text" class="form-control input-sm nums" name="list_rows" value="{php}echo input('param.list_rows', '') == '' ? config('list_rows') : input('param.list_rows');{/php}">
|
||||||
|
<input type="submit" class="hidden">
|
||||||
|
/ <strong>{$row_list->lastPage()}</strong> 页,共 <strong>{$row_list->total()}</strong> 条数据,每页显示数量
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
182
application/admin/view/module/install.html
Normal file
182
application/admin/view/module/install.html
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
{extend name="layout" /}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="block">
|
||||||
|
<div class="block-header bg-gray-lighter">
|
||||||
|
<ul class="block-options">
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="refresh_toggle" data-action-mode="demo"><i class="si si-refresh"></i></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="content_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="close"><i class="si si-close"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="block-title">{$page_title|default=""}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block-content tab-content">
|
||||||
|
<div class="tab-pane active">
|
||||||
|
<div class="block-content">
|
||||||
|
<form class="form-horizontal form-builder" action="{:url('install')}" method="get">
|
||||||
|
<input type="hidden" name="name" value="{$name|default=''}">
|
||||||
|
<input type="hidden" name="confirm" value="1">
|
||||||
|
<div class="form-group">
|
||||||
|
<h4 class="col-xs-12 push-10">模块依赖检查</h4>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
{empty name="need_module"}
|
||||||
|
<div class="form-control-static">无需依赖其他模块</div>
|
||||||
|
{else/}
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>模块</th>
|
||||||
|
<th>唯一标识</th>
|
||||||
|
<th style="width: 100px;">当前版本</th>
|
||||||
|
<th style="width: 100px;">所需版本</th>
|
||||||
|
<th class="text-center" style="width: 100px;">检查结果</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{volist name="need_module" id="vo"}
|
||||||
|
<tr>
|
||||||
|
<td>{$vo.module}</td>
|
||||||
|
<td><a href="http://www.dolphinphp.com" target="_blank" data-toggle="tooltip" title="到商城查看该模块">{$vo.identifier}</a></td>
|
||||||
|
<td>{$vo.version}</td>
|
||||||
|
<td>{$vo.version_need}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{$vo.result|raw}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/volist}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{/empty}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<h4 class="col-xs-12 push-10">插件依赖检查</h4>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
{empty name="need_plugin"}
|
||||||
|
<div class="form-control-static">无需依赖其他插件</div>
|
||||||
|
{else/}
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>插件</th>
|
||||||
|
<th>唯一标识</th>
|
||||||
|
<th style="width: 100px;">当前版本</th>
|
||||||
|
<th style="width: 100px;">所需版本</th>
|
||||||
|
<th class="text-center" style="width: 100px;">检查结果</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{volist name="need_plugin" id="vo"}
|
||||||
|
<tr>
|
||||||
|
<td>{$vo.plugin}</td>
|
||||||
|
<td><a href="http://www.dolphinphp.com" target="_blank" data-toggle="tooltip" title="到商城查看该插件">{$vo.identifier}</a></td>
|
||||||
|
<td>{$vo.version}</td>
|
||||||
|
<td>{$vo.version_need}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{$vo.result|raw}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/volist}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{/empty}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<h4 class="col-xs-12 push-10">数据表检查</h4>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
{empty name="table_check"}
|
||||||
|
<div class="form-control-static">该模块不需要数据表</div>
|
||||||
|
{else/}
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>数据表</th>
|
||||||
|
<th class="text-center" style="width: 100px;">检查结果</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{volist name="table_check" id="vo"}
|
||||||
|
<tr>
|
||||||
|
<td>{$vo.table}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{$vo.result|raw}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/volist}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{/empty}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group " id="form_group_group">
|
||||||
|
<h4 class="col-xs-12 push-10">是否清除旧数据</h4>
|
||||||
|
<div class="col-xs-9">
|
||||||
|
<label class="css-input css-radio css-radio-primary css-radio-sm push-10-r">
|
||||||
|
<input type="radio" name="clear" id="clear1" value="0" checked="">
|
||||||
|
<span></span> 否
|
||||||
|
</label>
|
||||||
|
<label class="css-input css-radio css-radio-primary css-radio-sm push-10-r">
|
||||||
|
<input type="radio" name="clear" id="clear2" value="1">
|
||||||
|
<span></span> 是
|
||||||
|
</label>
|
||||||
|
<div class="help-block">
|
||||||
|
选择“是”,将删除数据库中已存在的相同数据表
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-minw btn-primary" type="button" id="install">
|
||||||
|
安装
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-default" type="button" onclick="javascript:history.back(-1);return false;">
|
||||||
|
返回
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block name="script"}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$('#install').click(function () {
|
||||||
|
var table_exists = false;
|
||||||
|
|
||||||
|
if ($('.form-builder i.text-danger').length) {
|
||||||
|
Dolphin.notify('缺少依赖模块或插件', 'danger');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($('.form-builder span.text-danger').length) {
|
||||||
|
table_exists = true;
|
||||||
|
}
|
||||||
|
if (table_exists && $('.form-builder input[name=clear]:checked').val() == 0) {
|
||||||
|
Dolphin.notify('数据库表存在冲突,如果需要覆盖原有数据,请选择“清除旧数据”', 'danger');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.form-builder').submit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{/block}
|
64
application/admin/view/module/uninstall.html
Normal file
64
application/admin/view/module/uninstall.html
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{extend name="layout" /}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="block">
|
||||||
|
<div class="block-header bg-gray-lighter">
|
||||||
|
<ul class="block-options">
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="refresh_toggle" data-action-mode="demo"><i class="si si-refresh"></i></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="content_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="close"><i class="si si-close"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="block-title">{$page_title|default=""}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block-content tab-content">
|
||||||
|
<div class="tab-pane active">
|
||||||
|
<div class="block-content">
|
||||||
|
<form class="form-horizontal form-builder" action="{:url('uninstall')}" method="get">
|
||||||
|
<input type="hidden" name="name" value="{$name|default=''}">
|
||||||
|
<input type="hidden" name="confirm" value="1">
|
||||||
|
<div class="form-group " id="form_group_group">
|
||||||
|
<h4 class="col-xs-12 push-10">是否清除数据</h4>
|
||||||
|
<div class="col-xs-9">
|
||||||
|
<label class="css-input css-radio css-radio-primary css-radio-sm push-10-r">
|
||||||
|
<input type="radio" name="clear" id="clear1" value="0" checked="">
|
||||||
|
<span></span> 否
|
||||||
|
</label>
|
||||||
|
<label class="css-input css-radio css-radio-primary css-radio-sm push-10-r">
|
||||||
|
<input type="radio" name="clear" id="clear2" value="1">
|
||||||
|
<span></span> 是
|
||||||
|
</label>
|
||||||
|
<div class="help-block">
|
||||||
|
选择“是”,将删除数据库中的数据表
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-minw btn-danger" type="submit" id="uninstall">
|
||||||
|
卸载
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-default" type="button" onclick="javascript:history.back(-1);return false;">
|
||||||
|
返回
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
164
application/admin/view/plugin/index.html
Normal file
164
application/admin/view/plugin/index.html
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
{extend name="layout" /}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="block">
|
||||||
|
{notempty name="tab_nav"}
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
{volist name="tab_nav['tab_list']" id="tab"}
|
||||||
|
<li {eq name="tab_nav.curr_tab" value="$key"}class="active"{/eq}>
|
||||||
|
<a href="{$tab.url}">{$tab.title}</a>
|
||||||
|
</li>
|
||||||
|
{/volist}
|
||||||
|
<li class="pull-right">
|
||||||
|
<ul class="block-options push-10-t push-10-r">
|
||||||
|
<li>
|
||||||
|
<a href="{:url('index', ['type' => $type])}"><i class="si si-{$type=='list' ? 'list' : 'grid'}"></i></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{else/}
|
||||||
|
<div class="block-header bg-gray-lighter">
|
||||||
|
<ul class="block-options">
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="fullscreen_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="refresh_toggle" data-action-mode="demo"><i class="si si-refresh"></i></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="content_toggle"></button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" data-toggle="block-option" data-action="close"><i class="si si-close"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 class="block-title">{$page_title}</h3>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
<div class="block-content tab-content">
|
||||||
|
<div class="tab-pane active">
|
||||||
|
<div class="row push-20">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="pull-right search-bar">
|
||||||
|
<form class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-search"></i></span>
|
||||||
|
<input type="text" class="form-control" value="{:input('get.keyword')}" name="keyword" placeholder="请输入标识/名称/作者">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="toolbar-btn-action">
|
||||||
|
<a title="全部" class="btn btn-default" href="{:url('index')}">全部({$total.all|default='0'})</a>
|
||||||
|
<a title="已启用" class="btn btn-success" href="{:url('index', ['status' => '1'])}">已启用({$total['1']|default='0'})</a>
|
||||||
|
<a title="已禁用" class="btn btn-warning" href="{:url('index', ['status' => '0'])}">已禁用({$total['0']|default='0'})</a>
|
||||||
|
<a title="未安装" class="btn btn-info" href="{:url('index', ['status' => '-1'])}">未安装({$total['-1']|default='0'})</a>
|
||||||
|
<a title="已损坏" class="btn btn-danger" href="{:url('index', ['status' => '-2'])}" id="hide_disable">已损坏({$total['-2']|default='0'})</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row module-list push-20">
|
||||||
|
{empty name="plugins"}
|
||||||
|
<div class="table-empty">
|
||||||
|
<div class="text-center empty-info">
|
||||||
|
<i class="fa fa-database"></i> 暂无数据<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/empty}
|
||||||
|
{eq name="type" value="block"}
|
||||||
|
{volist name="plugins" id="plugin"}
|
||||||
|
<div class="col-sm-6 col-md-4 col-lg-3">
|
||||||
|
<div class="block block-rounded">
|
||||||
|
<div class="block-content block-content-full text-center bg-{$plugin.bg_color|default='danger'} ribbon ribbon-bookmark ribbon-crystal">
|
||||||
|
<div class="ribbon-box font-w600">{$plugin.version|default='无版本号'}</div>
|
||||||
|
<div class="item item-2x item-circle bg-crystal-op push-20-t push-20 visibility-hidden" data-toggle="appear" data-offset="50" data-class="animated fadeIn">
|
||||||
|
<i class="{$plugin.icon|default='fa fa-puzzle-piece'} text-white-op"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="h4 text-white">{$plugin.title|default='无插件标题'}</h3>
|
||||||
|
<div class="text-white-op">
|
||||||
|
<em>{$plugin.name|default=''}</em>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="block-content bg-gray-lighter">
|
||||||
|
<div class="{$plugin.status_class} pull-right push-10-l">{$plugin.status_info|raw}</div>
|
||||||
|
<div class="push-10">
|
||||||
|
<a class="h5" href="{$plugin.author_url|default=''}" target="_blank"><i class="fa fa-user"></i> {$plugin.author|default=''}</a>
|
||||||
|
</div>
|
||||||
|
<div class="push-10 mheight-100">
|
||||||
|
<div data-toggle="slimscroll" data-height="110px">
|
||||||
|
<p class="text-gray-dark">{$plugin.description|raw|default='暂无简介'}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center push">
|
||||||
|
{$plugin.actions|raw}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/volist}
|
||||||
|
{else/}
|
||||||
|
{notempty name="plugins"}
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="builder-table-wrapper" id="builder-table-wrapper">
|
||||||
|
<div class="builder-table" id="builder-table">
|
||||||
|
<table class="table table-builder table-hover table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>名称</th>
|
||||||
|
<th>图标</th>
|
||||||
|
<th>版本</th>
|
||||||
|
<th>作者</th>
|
||||||
|
<th>简介</th>
|
||||||
|
<th class="column-right_button" style="min-width:180px">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{volist name="plugins" id="plugin"}
|
||||||
|
<tr>
|
||||||
|
<td>{$plugin.title|default='无插件标题'}</td>
|
||||||
|
<td><i class="{$plugin.icon|default='fa fa-puzzle-piece'}"></i></td>
|
||||||
|
<td>{$plugin.version|default='无版本号'}</td>
|
||||||
|
<td><a href="{$plugin.author_url|default=''}" target="_blank">{$plugin.author|default=''}</a></td>
|
||||||
|
<td>{$plugin.description|raw|default='暂无简介'}</td>
|
||||||
|
<td>{$plugin.actions|raw}</td>
|
||||||
|
</tr>
|
||||||
|
{/volist}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
{/eq}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="data-table-toolbar">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
{// 分页 }
|
||||||
|
{notempty name="pages"}
|
||||||
|
{$pages}
|
||||||
|
{/notempty}
|
||||||
|
{notempty name="row_list"}
|
||||||
|
<div class="pagination-info pull-right">
|
||||||
|
<form action="" method="get">
|
||||||
|
<input type="text" class="form-control input-sm go-page" name="page" value="{:input('param.page', '1')}">
|
||||||
|
<input type="text" class="form-control input-sm nums" name="list_rows" value="{php}echo input('param.list_rows', '') == '' ? config('list_rows') : input('param.list_rows');{/php}">
|
||||||
|
<input type="submit" class="hidden">
|
||||||
|
/ <strong>{$row_list->lastPage()}</strong> 页,共 <strong>{$row_list->total()}</strong> 条数据,每页显示数量
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{/notempty}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
298
application/cms/admin/Advert.php
Normal file
298
application/cms/admin/Advert.php
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Advert as AdvertModel;
|
||||||
|
use app\cms\model\AdvertType as AdvertTypeModel;
|
||||||
|
use think\facade\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Advert extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 广告列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = AdvertModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
$btnType = [
|
||||||
|
'class' => 'btn btn-info',
|
||||||
|
'title' => '广告分类',
|
||||||
|
'icon' => 'fa fa-fw fa-sitemap',
|
||||||
|
'href' => url('advert_type/index')
|
||||||
|
];
|
||||||
|
|
||||||
|
$list_type = AdvertTypeModel::where('status', 1)->column('id,name');
|
||||||
|
array_unshift($list_type, '默认分类');
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['name', '广告名称', 'text.edit'],
|
||||||
|
['typeid', '分类', 'select', $list_type],
|
||||||
|
['ad_type', '类型', 'text', '', ['代码', '文字', '图片', 'flash']],
|
||||||
|
['timeset', '时间限制', 'text', '', ['永不过期', '限时']],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('add,enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addTopButton('custom', $btnType) // 添加顶部按钮
|
||||||
|
->addRightButtons(['edit', 'delete' => ['data-tips' => '删除后无法恢复。']]) // 批量添加右侧按钮
|
||||||
|
->addOrder('id,name,typeid,timeset,ad_type,create_time,update_time')
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->addValidate('Advert', 'name')
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Advert');
|
||||||
|
if (true !== $result) $this->error($result);
|
||||||
|
if ($data['ad_type'] != 0) {
|
||||||
|
$data['link'] == '' && $this->error('链接不能为空');
|
||||||
|
Validate::is($data['link'], 'url') === false && $this->error('链接不是有效的url地址'); // true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 广告类型
|
||||||
|
switch ($data['ad_type']) {
|
||||||
|
case 0: // 代码
|
||||||
|
$data['content'] = $data['code'];
|
||||||
|
break;
|
||||||
|
case 1: // 文字
|
||||||
|
$data['content'] = '<a href="'.$data['link'].'" target="_blank" style="';
|
||||||
|
if ($data['size'] != '') {
|
||||||
|
$data['content'] .= 'font-size:'.$data['size'].'px;';
|
||||||
|
}
|
||||||
|
if ($data['color'] != '') {
|
||||||
|
$data['content'] .= 'color:'.$data['color'];
|
||||||
|
}
|
||||||
|
$data['content'] .= '">'.$data['title'].'</a>';
|
||||||
|
break;
|
||||||
|
case 2: // 图片
|
||||||
|
$data['content'] = '<a href="'.$data['link'].'" target="_blank"><img src="'.get_file_path($data['src']).'" style="';
|
||||||
|
if ($data['width'] != '') {
|
||||||
|
$data['content'] .= 'width:'.$data['width'].'px;';
|
||||||
|
}
|
||||||
|
if ($data['height'] != '') {
|
||||||
|
$data['content'] .= 'height:'.$data['height'].'px;';
|
||||||
|
}
|
||||||
|
if ($data['alt'] != '') {
|
||||||
|
$data['content'] .= '" alt="'.$data['alt'];
|
||||||
|
}
|
||||||
|
$data['content'] .= '" /></a>';
|
||||||
|
break;
|
||||||
|
case 3: // flash
|
||||||
|
$data['content'] = '';
|
||||||
|
$data['content'] = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"';
|
||||||
|
if ($data['width'] != '') {
|
||||||
|
$data['content'] .= ' width="'.$data['width'].'"';
|
||||||
|
}
|
||||||
|
if ($data['height'] != '') {
|
||||||
|
$data['content'] .= ' height="'.$data['height'].'"';
|
||||||
|
}
|
||||||
|
$data['content'] .= '><param name="quality" value="high" /><param name="movie" value="'.$data['link'].'" /><embed allowfullscreen="true"';
|
||||||
|
if ($data['height'] != '') {
|
||||||
|
$data['content'] .= ' height="'.$data['height'].'"';
|
||||||
|
}
|
||||||
|
$data['content'] .= ' pluginspage="http://www.macromedia.com/go/getflashplayer" quality="high" src="'.$data['link'].'" type="application/x-shockwave-flash"';
|
||||||
|
if ($data['width'] != '') {
|
||||||
|
$data['content'] .= ' width="'.$data['width'].'"';
|
||||||
|
}
|
||||||
|
$data['content'] .= '></embed></object>';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($advert = AdvertModel::create($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('advert_add', 'cms_advert', $advert['id'], UID, $data['name']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$list_type = AdvertTypeModel::where('status', 1)->column('id,name');
|
||||||
|
array_unshift($list_type, '默认分类');
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTips('如果出现无法添加的情况,可能由于浏览器将本页面当成了广告,请尝试关闭浏览器的广告过滤功能再试。', 'warning')
|
||||||
|
->addFormItems([
|
||||||
|
['select', 'typeid', '广告分类', '', $list_type, 0],
|
||||||
|
['text', 'tagname', '广告位标识', '由小写字母、数字或下划线组成,不能以数字开头'],
|
||||||
|
['text', 'name', '广告位名称'],
|
||||||
|
['radio', 'timeset', '时间限制', '', ['永不过期', '在设内时间内有效'], 0],
|
||||||
|
['daterange', 'start_time,end_time', '开始时间-结束时间'],
|
||||||
|
['radio', 'ad_type', '广告类型', '', ['代码', '文字', '图片', 'flash'], 0],
|
||||||
|
['textarea', 'code', '代码', '<code>必填</code>,支持html代码'],
|
||||||
|
['image', 'src', '图片', '<code>必须</code>'],
|
||||||
|
['text', 'title', '文字内容', '<code>必填</code>'],
|
||||||
|
['text', 'link', '链接', '<code>必填</code>'],
|
||||||
|
['colorpicker', 'color', '文字颜色', '', '', 'rgb'],
|
||||||
|
['text', 'size', '文字大小', '只需填写数字,例如:12,表示12px', '', ['', 'px']],
|
||||||
|
['text', 'width', '宽度', '不用填写单位,只需填写具体数字'],
|
||||||
|
['text', 'height', '高度', '不用填写单位,只需填写具体数字'],
|
||||||
|
['text', 'alt', '图片描述', '即图片alt的值'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->setTrigger('ad_type', '0', 'code')
|
||||||
|
->setTrigger('ad_type', '1', 'title,color,size')
|
||||||
|
->setTrigger('ad_type', '2', 'src,alt')
|
||||||
|
->setTrigger('ad_type', '2,3', 'width,height')
|
||||||
|
->setTrigger('ad_type', '1,2,3', 'link')
|
||||||
|
->setTrigger('timeset', '1', 'start_time')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param null $id 广告id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Advert');
|
||||||
|
if (true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (AdvertModel::update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('advert_edit', 'cms_advert', $id, UID, $data['name']);
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$list_type = AdvertTypeModel::where('status', 1)->column('id,name');
|
||||||
|
array_unshift($list_type, '默认分类');
|
||||||
|
|
||||||
|
$info = AdvertModel::get($id);
|
||||||
|
$info['ad_type'] = ['代码', '文字', '图片', 'flash'][$info['ad_type']];
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTips('如果出现无法添加的情况,可能由于浏览器将本页面当成了广告,请尝试关闭浏览器的广告过滤功能再试。', 'warning')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['hidden', 'tagname'],
|
||||||
|
['static', 'tagname', '广告位标识'],
|
||||||
|
['static', 'ad_type', '广告类型'],
|
||||||
|
['text', 'name', '广告位名称'],
|
||||||
|
['select', 'typeid', '广告分类', '', $list_type],
|
||||||
|
['radio', 'timeset', '时间限制', '', ['永不过期', '在设内时间内有效']],
|
||||||
|
['daterange', 'start_time,end_time', '开始时间-结束时间'],
|
||||||
|
['textarea', 'content', '广告内容'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']]
|
||||||
|
])
|
||||||
|
->setTrigger('timeset', '1', 'start_time')
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除广告
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用广告
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用广告
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置广告状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$advert_name = AdvertModel::where('id', 'in', $ids)->column('name');
|
||||||
|
return parent::setStatus($type, ['advert_'.$type, 'cms_advert', 0, UID, implode('、', $advert_name)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$advert = AdvertModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $advert . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['advert_edit', 'cms_advert', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
196
application/cms/admin/AdvertType.php
Normal file
196
application/cms/admin/AdvertType.php
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\AdvertType as AdvertTypeModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告分类控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class AdvertType extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 广告列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = AdvertTypeModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['name' => '分类名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['name', '分类名称', 'text.edit'],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->setTableName('cms_advert_type')
|
||||||
|
->addTopButton('back', ['href' => url('advert/index')]) // 批量添加顶部按钮
|
||||||
|
->addTopButtons('add,enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons(['edit', 'delete' => ['data-tips' => '删除后无法恢复。']]) // 批量添加右侧按钮
|
||||||
|
->addOrder('id,name,create_time,update_time')
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->addValidate('AdvertType', 'name')
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'AdvertType');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($type = AdvertTypeModel::create($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('advert_type_add', 'cms_advert_type', $type['id'], UID, $data['name']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTips('如果出现无法添加的情况,可能由于浏览器将本页面当成了广告,请尝试关闭浏览器的广告过滤功能再试。', 'warning')
|
||||||
|
->addFormItems([
|
||||||
|
['text', 'name', '分类名称'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param null $id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'AdvertType');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (AdvertTypeModel::update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('advert_type_edit', 'cms_advert_type', $id, UID, $data['name']);
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = AdvertTypeModel::get($id);
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTips('如果出现无法编辑的情况,可能由于浏览器将本页面当成了广告,请尝试关闭浏览器的广告过滤功能再试。', 'warning')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['text', 'name', '分类名称'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']]
|
||||||
|
])
|
||||||
|
->setFormdata($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除广告分类
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用广告分类
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用广告分类
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置广告分类状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record 日志记录
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$type_name = AdvertTypeModel::where('id', 'in', $ids)->column('name');
|
||||||
|
return parent::setStatus($type, ['advert_type_'.$type, 'cms_advert_type', 0, UID, implode('、', $type_name)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$type = AdvertTypeModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $type . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['advert_type_edit', 'cms_advert_type', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
279
application/cms/admin/Column.php
Normal file
279
application/cms/admin/Column.php
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Model as DocumentModel;
|
||||||
|
use app\cms\model\Column as ColumnModel;
|
||||||
|
use app\cms\model\Document;
|
||||||
|
use app\user\model\Role as RoleModel;
|
||||||
|
use util\Tree;
|
||||||
|
use util\File;
|
||||||
|
use think\facade\Env;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 栏目控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Column extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 栏目列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
|
||||||
|
// 数据列表
|
||||||
|
$data_list = ColumnModel::where($map)->column(true);
|
||||||
|
if (empty($map)) {
|
||||||
|
$data_list = Tree::config(['title' => 'name'])->toList($data_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义按钮
|
||||||
|
$btnMove = [
|
||||||
|
'class' => 'btn btn-xs btn-default js-move-column',
|
||||||
|
'icon' => 'fa fa-fw fa-arrow-circle-right',
|
||||||
|
'title' => '移动栏目'
|
||||||
|
];
|
||||||
|
$btnAdd = [
|
||||||
|
'class' => 'btn btn-xs btn-default',
|
||||||
|
'icon' => 'fa fa-fw fa-plus',
|
||||||
|
'title' => '新增子栏目',
|
||||||
|
'href' => url('add', ['pid' => '__id__'])
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['name' => '栏目名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['icon', '图标', 'icon'],
|
||||||
|
['name', '栏目名称', 'callback', function($value, $data){
|
||||||
|
return isset($data['title_prefix']) ? $data['title_display'] : $value;
|
||||||
|
}, '__data__'],
|
||||||
|
['model', '内容模型', 'select', DocumentModel::getTitleList()],
|
||||||
|
['rank_auth', '浏览权限', 'select', RoleModel::getTree(null, '开放浏览')],
|
||||||
|
['hide', '是否隐藏', 'yesno'],
|
||||||
|
['post_auth', '支持投稿', 'yesno'],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('add,enable,disable') // 批量添加顶部按钮
|
||||||
|
->addRightButton('custom', $btnAdd)
|
||||||
|
->addRightButton('edit') // 添加右侧按钮
|
||||||
|
// ->addRightButton('custom', $btnMove)
|
||||||
|
->addRightButton('delete', ['data-tips' => '删除栏目前,请确保无子栏目和文档!']) // 添加右侧按钮
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增栏目
|
||||||
|
* @param int $pid 父级id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add($pid = 0)
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Column');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($column = ColumnModel::create($data)) {
|
||||||
|
cache('cms_column_list', null);
|
||||||
|
// 记录行为
|
||||||
|
action_log('column_add', 'cms_column', $column['id'], UID, $data['name']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$template_list = File::get_dirs(Env::get('app_path').'cms/view/column/')['file'];
|
||||||
|
$template_detail = File::get_dirs(Env::get('app_path').'cms/view/document/')['file'];
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['select', 'pid', '所属栏目', '<span class="text-danger">必选</span>', ColumnModel::getTreeList(), $pid],
|
||||||
|
['text', 'name', '栏目名称', '<span class="text-danger">必填</span>'],
|
||||||
|
['radio', 'model', '内容模型', '<span class="text-danger">必选</span>', DocumentModel::getTitleList()],
|
||||||
|
['radio', 'type', '栏目属性', '', ['最终列表栏目', '外部链接'], 0],
|
||||||
|
['text', 'url', '链接', '可以填写完整的url,如:<code>http://www.dolphinphp.com</code>,也可以填写 <code>模块/控制器/操作</code>,如:<code>cms/index/index</code>'],
|
||||||
|
['radio', 'target', '打开方式', '', ['_self' => '当前窗口', '_blank' => '新窗口'], '_self'],
|
||||||
|
// ['select', 'index_template', '封面页模板', '可选'],
|
||||||
|
['select', 'list_template', '列表页模板', '可选,模板目录: <code>cms/view/column</code>', parse_array($template_list)],
|
||||||
|
['select', 'detail_template', '详情页模板', '可选,模板目录: <code>cms/view/document</code>', parse_array($template_detail)],
|
||||||
|
['ckeditor', 'content', '栏目内容', '可作为单页使用'],
|
||||||
|
['icon', 'icon', '图标'],
|
||||||
|
['radio', 'post_auth', '是否支持投稿', '是否允许前台用户投稿', ['禁止投稿', '允许投稿'], 1],
|
||||||
|
['radio', 'hide', '是否隐藏栏目', '隐藏后前台不可见', ['显示', '隐藏'], 0],
|
||||||
|
['select', 'rank_auth', '浏览权限', '', RoleModel::getTree(null, '开放浏览'), 0],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1],
|
||||||
|
['text', 'sort', '排序', '', 100],
|
||||||
|
])
|
||||||
|
->setTrigger('type', '0,2', 'index_template,list_template,detail_template')
|
||||||
|
->setTrigger('type', '1', 'url,target')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑栏目
|
||||||
|
* @param string $id 栏目id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = '')
|
||||||
|
{
|
||||||
|
if ($id === 0) $this->error('参数错误');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Column');
|
||||||
|
// 验证失败 输出错误信息
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (ColumnModel::update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('column_edit', 'cms_column', $id, UID, $data['name']);
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$info = ColumnModel::get($id);
|
||||||
|
|
||||||
|
$template_list = File::get_dirs(Env::get('app_path').'cms/view/column/')['file'];
|
||||||
|
$template_detail = File::get_dirs(Env::get('app_path').'cms/view/document/')['file'];
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['select', 'pid', '所属栏目', '<span class="text-danger">必选</span>', ColumnModel::getTreeList($id)],
|
||||||
|
['text', 'name', '栏目名称', '<span class="text-danger">必填</span>'],
|
||||||
|
['radio', 'model', '内容模型', '<span class="text-danger">必选</span>', DocumentModel::getTitleList()],
|
||||||
|
['radio', 'type', '栏目属性', '', ['最终列表栏目', '外部链接'], 0],
|
||||||
|
['text', 'url', '链接', '可以填写完整的url,如:<code>http://www.dolphinphp.com</code>,也可以填写 <code>模块/控制器/操作</code>,如:<code>cms/index/index</code>'],
|
||||||
|
['radio', 'target', '打开方式', '', ['_self' => '当前窗口', '_blank' => '新窗口'], '_self'],
|
||||||
|
// ['select', 'index_template', '封面页模板', '可选'],
|
||||||
|
['select', 'list_template', '列表页模板', '可选,模板目录: <code>cms/view/column</code>', parse_array($template_list)],
|
||||||
|
['select', 'detail_template', '详情页模板', '可选,模板目录: <code>cms/view/document</code>', parse_array($template_detail)],
|
||||||
|
['ckeditor', 'content', '栏目内容', '可作为单页使用'],
|
||||||
|
['icon', 'icon', '图标'],
|
||||||
|
['radio', 'post_auth', '是否支持投稿', '是否允许前台用户投稿', ['禁止投稿', '允许投稿']],
|
||||||
|
['radio', 'hide', '是否隐藏栏目', '隐藏后前台不可见', ['显示', '隐藏'], 0],
|
||||||
|
['select', 'rank_auth', '浏览权限', '', RoleModel::getTree(null, '开放浏览')],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']],
|
||||||
|
['text', 'sort', '排序'],
|
||||||
|
])
|
||||||
|
->setTrigger('type', '0,2', 'index_template,list_template,detail_template')
|
||||||
|
->setTrigger('type', '1', 'url,target')
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除栏目
|
||||||
|
* @param null $ids 栏目id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($ids = null)
|
||||||
|
{
|
||||||
|
if ($ids === null) $this->error('参数错误');
|
||||||
|
|
||||||
|
// 检查是否有子栏目
|
||||||
|
if (ColumnModel::where('pid', $ids)->find()) {
|
||||||
|
$this->error('请先删除或移动该栏目下的子栏目');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有文档
|
||||||
|
if (Document::where('cid', $ids)->find()) {
|
||||||
|
$this->error('请先删除或移动该栏目下的所有文档');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除并记录日志
|
||||||
|
$column_name = get_column_name($ids);
|
||||||
|
return parent::delete(['column_delete', 'cms_column', 0, UID, $column_name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用栏目
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用栏目
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置栏目状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$column_delete = is_array($ids) ? '' : $ids;
|
||||||
|
$column_names = ColumnModel::where('id', 'in', $ids)->column('name');
|
||||||
|
return parent::setStatus($type, ['column_'.$type, 'cms_column', $column_delete, UID, implode('、', $column_names)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$column = ColumnModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $column . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['column_edit', 'cms_column', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
129
application/cms/admin/Content.php
Normal file
129
application/cms/admin/Content.php
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Document;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Content extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 空操作,用于显示各个模型的文档列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function _empty()
|
||||||
|
{
|
||||||
|
cookie('__forward__', $_SERVER['REQUEST_URI']);
|
||||||
|
$model_name = $this->request->action();
|
||||||
|
$model = Db::name('cms_model')->where('name', $model_name)->find();
|
||||||
|
if (!$model) $this->error('找不到该内容');
|
||||||
|
|
||||||
|
// 独立模型
|
||||||
|
if ($model['type'] == 2) {
|
||||||
|
$table_name = substr($model['table'], strlen(config('database.prefix')));
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
$map[] = ['trash', '=', 0];
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = Db::view($table_name, true)
|
||||||
|
->view("cms_column", ['name' => 'column_name'], 'cms_column.id='.$table_name.'.cid', 'left')
|
||||||
|
->view("admin_user", 'username', 'admin_user.id='.$table_name.'.uid', 'left')
|
||||||
|
->where($map)
|
||||||
|
->order($order)
|
||||||
|
->paginate();
|
||||||
|
|
||||||
|
$trash_count = Db::table($model['table'])->where('trash', 1)->count();
|
||||||
|
|
||||||
|
// 自定义按钮
|
||||||
|
$btnRecycle = [
|
||||||
|
'title' => '回收站('.$trash_count.')',
|
||||||
|
'icon' => 'fa fa-trash',
|
||||||
|
'class' => 'btn btn-info',
|
||||||
|
'href' => url('recycle/index', ['model' => $model['id']])
|
||||||
|
];
|
||||||
|
$columns = Db::name('cms_column')->where(['model' => $model['id']])->column('id,name');
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题', 'cms_column.name' => '栏目名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['title', '标题'],
|
||||||
|
['cid', '栏目名称', 'select', $columns],
|
||||||
|
['view', '点击量'],
|
||||||
|
['username', '发布人'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->setTableName($table_name)
|
||||||
|
->addTopButton('add', ['href' => url('document/add', ['model' => $model['id']])]) // 添加顶部按钮
|
||||||
|
->addTopButton('enable', ['href' => url('document/enable', ['table' => $table_name])]) // 添加顶部按钮
|
||||||
|
->addTopButton('disable', ['href' => url('document/disable', ['table' => $table_name])]) // 添加顶部按钮
|
||||||
|
->addTopButton('delete', ['href' => url('document/delete', ['table' => $table_name])]) // 添加顶部按钮
|
||||||
|
->addTopButton('custom', $btnRecycle) // 添加顶部按钮
|
||||||
|
->addRightButton('edit', ['href' => url('document/edit', ['model' => $model['id'], 'id' => '__id__'])]) // 添加右侧按钮
|
||||||
|
->addRightButton('delete', ['href' => url('document/delete', ['ids' => '__id__', 'table' => $table_name])]) // 添加右侧按钮
|
||||||
|
->addOrder('id,title,cid,view,username,update_time')
|
||||||
|
->addFilter('cid', $columns)
|
||||||
|
->addFilter(['username' => 'admin_user'])
|
||||||
|
->addFilterMap(['cid' => ['model' => $model['id']]])
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
} else {
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
$map[] = ['cms_document.trash', '=', 0];
|
||||||
|
$map[] = ['cms_document.model', '=', $model['id']];
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = Document::getList($map, $order);
|
||||||
|
|
||||||
|
$columns = Db::name('cms_column')->where(['model' => $model['id']])->column('id,name');
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题', 'cms_column.name' => '栏目名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['title', '标题'],
|
||||||
|
['cid', '栏目名称', 'select', $columns],
|
||||||
|
['view', '点击量'],
|
||||||
|
['username', '发布人'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->setTableName('cms_document')
|
||||||
|
->addTopButton('add', ['href' => url('document/add', ['model' => $model['id']])]) // 添加顶部按钮
|
||||||
|
->addTopButton('enable', ['href' => url('document/enable', ['table' => 'cms_document'])]) // 添加顶部按钮
|
||||||
|
->addTopButton('disable', ['href' => url('document/disable', ['table' => 'cms_document'])]) // 添加顶部按钮
|
||||||
|
->addTopButton('delete', ['href' => url('document/delete', ['table' => 'cms_document'])]) // 添加顶部按钮
|
||||||
|
->addRightButton('edit', ['href' => url('document/edit', ['id' => '__id__'])]) // 添加右侧按钮
|
||||||
|
->addRightButton('delete', ['href' => url('document/delete', ['ids' => '__id__', 'table' => 'cms_document'])]) // 添加右侧按钮
|
||||||
|
->addOrder('id,title,cid,view,username,update_time')
|
||||||
|
->addFilter('cid', $columns)
|
||||||
|
->addFilter(['username' => 'admin_user'])
|
||||||
|
->addFilterMap(['cid' => ['model' => $model['id']]])
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
337
application/cms/admin/Document.php
Normal file
337
application/cms/admin/Document.php
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Column as ColumnModel;
|
||||||
|
use app\cms\model\Document as DocumentModel;
|
||||||
|
use app\cms\model\Field as FieldModel;
|
||||||
|
use think\Db;
|
||||||
|
use util\Tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Document extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 文档列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
cookie('__forward__', $_SERVER['REQUEST_URI']);
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
$map[] = ['cms_document.trash', '=', 0];
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = DocumentModel::getList($map, $order);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题', 'cms_column.name' => '栏目名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['title', '标题'],
|
||||||
|
['column_name', '栏目名称'],
|
||||||
|
['view', '点击量'],
|
||||||
|
['username', '发布人'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('add,enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons(['edit', 'delete']) // 批量添加右侧按钮
|
||||||
|
->addOrder(['column_name' => 'cms_document.cid'])
|
||||||
|
->addOrder('id,title,view,username,update_time')
|
||||||
|
->addFilter(['column_name' => 'cms_column.name', 'username' => 'admin_user'])
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加文档
|
||||||
|
* @param int $cid 栏目id
|
||||||
|
* @param string $model 模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add($cid = 0, $model = '')
|
||||||
|
{
|
||||||
|
// 保存文档数据
|
||||||
|
if ($this->request->isAjax()) {
|
||||||
|
$DocumentModel = new DocumentModel();
|
||||||
|
if (false === $DocumentModel->saveData()) {
|
||||||
|
$this->error($DocumentModel->getError());
|
||||||
|
}
|
||||||
|
$this->success('新增成功', cookie('__forward__'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第二步,填写文档信息
|
||||||
|
if ($cid > 0) {
|
||||||
|
cookie('__forward__', url('add', ['cid' => $cid]));
|
||||||
|
// 获取栏目数据
|
||||||
|
$column = ColumnModel::getInfo($cid);
|
||||||
|
|
||||||
|
// 独立模型只取该模型的字段,不包含系统字段
|
||||||
|
$where = [];
|
||||||
|
if (get_model_type($column['model']) == 2) {
|
||||||
|
$where[] = ['model', '=', $column['model']];
|
||||||
|
} else {
|
||||||
|
$where[] = ['model', 'in', [0, $column['model']]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文档模型字段
|
||||||
|
$where[] = ['status', '=', 1];
|
||||||
|
$where[] = ['show', '=', 1];
|
||||||
|
$fields = FieldModel::where($where)->order('sort asc,id asc')->column(true);
|
||||||
|
|
||||||
|
foreach ($fields as &$value) {
|
||||||
|
// 解析options
|
||||||
|
if ($value['options'] != '') {
|
||||||
|
$value['options'] = parse_attr($value['options']);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($value['type']) {
|
||||||
|
case 'linkage':// 解析联动下拉框异步请求地址
|
||||||
|
if (!empty($value['ajax_url']) && substr($value['ajax_url'], 0, 4) != 'http') {
|
||||||
|
$value['ajax_url'] = url($value['ajax_url']);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'date':
|
||||||
|
case 'time':
|
||||||
|
case 'datetime':
|
||||||
|
$value['value'] = '';
|
||||||
|
break;
|
||||||
|
case 'bmap':
|
||||||
|
$value['level'] = $value['level'] == 0 ? 12 : $value['level'];
|
||||||
|
break;
|
||||||
|
case 'colorpicker':
|
||||||
|
$value['mode'] = 'rgba';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加额外表单项信息
|
||||||
|
$extra_field = [
|
||||||
|
['name' => 'cid', 'title' => '所属栏目', 'type' => 'static', 'value' => $column['name']],
|
||||||
|
['name' => 'cid', 'type' => 'hidden', 'value' => $cid],
|
||||||
|
['name' => 'model', 'type' => 'hidden', 'value' => $column['model']]
|
||||||
|
];
|
||||||
|
$fields = array_merge($extra_field, $fields);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setFormItems($fields)
|
||||||
|
->hideBtn('back')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第一步,选择栏目
|
||||||
|
if ($model == '') {
|
||||||
|
$columns = ColumnModel::getTreeList(0, false);
|
||||||
|
} else {
|
||||||
|
// 获取相同内容模型的栏目
|
||||||
|
$columns = Db::name('cms_column')->where('model', $model)->order('pid,id')->column('id,name,pid');
|
||||||
|
$columns = Tree::config(['title' => 'name'])->toList($columns, current($columns)['pid']);
|
||||||
|
$result = [];
|
||||||
|
foreach ($columns as $column) {
|
||||||
|
$result[$column['id']] = $column['title_display'];
|
||||||
|
}
|
||||||
|
$columns = $result;
|
||||||
|
}
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItem('select', 'cid', '选择栏目', '请选择栏目', $columns)
|
||||||
|
->setBtnTitle('submit', '下一步')
|
||||||
|
->hideBtn('back')
|
||||||
|
->isAjax(false)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑文档
|
||||||
|
* @param null $id 文档id
|
||||||
|
* @param string $model 模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null, $model = '')
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('参数错误');
|
||||||
|
|
||||||
|
// 保存文档数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$DocumentModel = new DocumentModel();
|
||||||
|
$result = $DocumentModel->saveData();
|
||||||
|
if (false === $result) {
|
||||||
|
$this->error($DocumentModel->getError());
|
||||||
|
}
|
||||||
|
$this->success('编辑成功', cookie('__forward__'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$info = DocumentModel::getOne($id, $model);
|
||||||
|
|
||||||
|
// 独立模型只取该模型的字段,不包含系统字段
|
||||||
|
$where = [];
|
||||||
|
if ($model != '') {
|
||||||
|
$where[] = ['model', '=', $model];
|
||||||
|
} else {
|
||||||
|
$where[] = ['model', 'in', [0, $info['model']]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用于查询内容模型栏目
|
||||||
|
$map = $where;
|
||||||
|
|
||||||
|
// 获取文档模型字段
|
||||||
|
$where[] = ['status', '=', 1];
|
||||||
|
$where[] = ['show', '=', 1];
|
||||||
|
$fields = FieldModel::where($where)->order('sort asc,id asc')->column(true);
|
||||||
|
|
||||||
|
foreach ($fields as $id => &$value) {
|
||||||
|
// 解析options
|
||||||
|
if ($value['options'] != '') {
|
||||||
|
$value['options'] = parse_attr($value['options']);
|
||||||
|
}
|
||||||
|
// 日期时间
|
||||||
|
switch ($value['type']) {
|
||||||
|
case 'date':
|
||||||
|
$info[$value['name']] = format_time($info[$value['name']], 'Y-m-d');
|
||||||
|
break;
|
||||||
|
case 'time':
|
||||||
|
$info[$value['name']] = format_time($info[$value['name']], 'H:i:s');
|
||||||
|
break;
|
||||||
|
case 'datetime':
|
||||||
|
$info[$value['name']] = empty($info[$value['name']]) ? '' : format_time($info[$value['name']]);
|
||||||
|
break;
|
||||||
|
case 'bmap':
|
||||||
|
$value['level'] = $value['level'] == 0 ? 12 : $value['level'];
|
||||||
|
break;
|
||||||
|
case 'colorpicker':
|
||||||
|
$value['mode'] = 'rgba';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取相同内容模型的栏目
|
||||||
|
$columns = Db::name('cms_column')->where($map)->whereOr('model', $info['model'])->order('pid,id')->column('id,name,pid');
|
||||||
|
$columns = Tree::config(['title' => 'name'])->toList($columns, current($columns)['pid']);
|
||||||
|
$result = [];
|
||||||
|
foreach ($columns as $column) {
|
||||||
|
$result[$column['id']] = $column['title_display'];
|
||||||
|
}
|
||||||
|
$columns = $result;
|
||||||
|
|
||||||
|
|
||||||
|
// 添加额外表单项信息
|
||||||
|
$extra_field = [
|
||||||
|
['name' => 'id', 'type' => 'hidden'],
|
||||||
|
['name' => 'cid', 'title' => '所属栏目', 'type' => 'select', 'options' => $columns],
|
||||||
|
['name' => 'model', 'type' => 'hidden']
|
||||||
|
];
|
||||||
|
$fields = array_merge($extra_field, $fields);
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建表单
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setFormItems($fields)
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文档(不是彻底删除,而是移动到回收站)
|
||||||
|
* @param null $ids 文档id
|
||||||
|
* @param string $table 数据表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function delete($ids = null, $table = '')
|
||||||
|
{
|
||||||
|
if ($ids === null) $this->error('参数错误');
|
||||||
|
|
||||||
|
$document_id = is_array($ids) ? '' : $ids;
|
||||||
|
$document_title = Db::name($table)->where('id', 'in', $ids)->column('title');
|
||||||
|
|
||||||
|
// 移动文档到回收站
|
||||||
|
if (false === Db::name($table)->where('id', 'in', $ids)->setField('trash', 1)) {
|
||||||
|
$this->error('删除失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除并记录日志
|
||||||
|
action_log('document_trash', $table, $document_id, UID, implode('、', $document_title));
|
||||||
|
$this->success('删除成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用文档
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用文档
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置文档状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$table_token = input('param._t', '');
|
||||||
|
$table_token == '' && $this->error('缺少参数');
|
||||||
|
!session('?'.$table_token) && $this->error('参数错误');
|
||||||
|
|
||||||
|
$table_data = session($table_token);
|
||||||
|
$table_name = $table_data['table'];
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$document_id = is_array($ids) ? '' : $ids;
|
||||||
|
$document_title = Db::name($table_name)->where('id', 'in', $ids)->column('title');
|
||||||
|
return parent::setStatus($type, ['document_'.$type, 'cms_document', $document_id, UID, implode('、', $document_title)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$table_token = input('param._t', '');
|
||||||
|
$table_token == '' && $this->error('缺少参数');
|
||||||
|
!session('?'.$table_token) && $this->error('参数错误');
|
||||||
|
|
||||||
|
$table_data = session($table_token);
|
||||||
|
$table = $table_data['table'];
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$document = Db::name($table)->where('id', $id)->value($field);
|
||||||
|
$details = '表名(' . $table . '),字段(' . $field . '),原值(' . $document . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['document_edit', 'cms_document', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
330
application/cms/admin/Field.php
Normal file
330
application/cms/admin/Field.php
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Field as FieldModel;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段管理控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Field extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 字段列表
|
||||||
|
* @param null $id 文档模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function index($id = null)
|
||||||
|
{
|
||||||
|
$id === null && $this->error('参数错误');
|
||||||
|
cookie('__forward__', $_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
$map['model'] = $id;
|
||||||
|
// 数据列表
|
||||||
|
$data_list = FieldModel::where($map)->order('id desc')->paginate();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['name' => '名称', 'title' => '标题']) // 设置搜索框
|
||||||
|
->setPageTips('【显示】表示新增或编辑文档时是否显示该字段<br>【启用】表示前台是否显示')
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['name', '名称'],
|
||||||
|
['title', '标题'],
|
||||||
|
['type', '类型', 'text', '', config('form_item_type')],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['show', '显示', 'switch'],
|
||||||
|
['status', '启用', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButton('back', ['href' => url('model/index')]) // 批量添加顶部按钮
|
||||||
|
->addTopButton('add', ['href' => url('add', ['model' => $id])]) // 添加顶部按钮
|
||||||
|
->addTopButtons('enable,disable') // 批量添加顶部按钮
|
||||||
|
->addRightButtons('edit,delete') // 批量添加右侧按钮
|
||||||
|
->replaceRightButton(['fixed' => 1], '<button class="btn btn-danger btn-xs" type="button" disabled>固定字段禁止操作</button>')
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增字段
|
||||||
|
* @param string $model 文档模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function add($model = '')
|
||||||
|
{
|
||||||
|
// 内容模型类别[0-系统,1-普通,2-独立]
|
||||||
|
$model_type = get_model_type($model);
|
||||||
|
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 非独立模型需验证字段名称是否为aid
|
||||||
|
if ($model_type != 2) {
|
||||||
|
// 非独立模型需验证新增的字段是否被系统占用
|
||||||
|
if ($data['name'] == 'aid' || is_default_field($data['name'])) {
|
||||||
|
$this->error('字段名称已存在');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->validate($data, 'Field');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
// 如果是快速联动
|
||||||
|
switch ($data['type']) {
|
||||||
|
case 'linkages':
|
||||||
|
$data['key'] = $data['key'] == '' ? 'id' : $data['key'];
|
||||||
|
$data['pid'] = $data['pid'] == '' ? 'pid' : $data['pid'];
|
||||||
|
$data['level'] = $data['level'] == '' ? '2' : $data['level'];
|
||||||
|
$data['option'] = $data['option'] == '' ? 'name' : $data['option'];
|
||||||
|
break;
|
||||||
|
case 'number':
|
||||||
|
$data['type'] = 'text';
|
||||||
|
break;
|
||||||
|
case 'bmap':
|
||||||
|
$data['level'] = !$data['level'] ? 12 : $data['level'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($field = FieldModel::create($data)) {
|
||||||
|
$FieldModel = new FieldModel();
|
||||||
|
// 添加字段
|
||||||
|
if ($FieldModel->newField($data)) {
|
||||||
|
// 记录行为
|
||||||
|
$details = '详情:文档模型('.get_model_title($data['model']).')、字段名称('.$data['name'].')、字段标题('.$data['title'].')、字段类型('.$data['type'].')';
|
||||||
|
action_log('field_add', 'cms_field', $field['id'], UID, $details);
|
||||||
|
// 清除缓存
|
||||||
|
cache('cms_system_fields', null);
|
||||||
|
$this->success('新增成功', cookie('__forward__'));
|
||||||
|
} else {
|
||||||
|
// 添加失败,删除新增的数据
|
||||||
|
FieldModel::destroy($field['id']);
|
||||||
|
$this->error($FieldModel->getError());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($model_type != 2) {
|
||||||
|
$field_exist = Db::name('cms_field')->where('model', 'in', [0, $model])->column('name');
|
||||||
|
$field_exist[] = 'aid';
|
||||||
|
} else {
|
||||||
|
$field_exist = ['id','cid','uid','title','model','create_time','update_time','sort','status','view','trash'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->setPageTips('以下字段名称已存在,请不要建立同名的字段:<br>'. implode('、', $field_exist))
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'model', $model],
|
||||||
|
['text', 'name', '字段名称', '由小写英文字母和下划线组成'],
|
||||||
|
['text', 'title', '字段标题', '可填写中文'],
|
||||||
|
['select', 'type', '字段类型', '', config('form_item_type')],
|
||||||
|
['text', 'define', '字段定义', '可根据实际需求自行填写或修改,但必须是正确的sql语法'],
|
||||||
|
['text', 'value', '字段默认值'],
|
||||||
|
['textarea', 'options', '额外选项', '用于单选、多选、下拉、联动等类型'],
|
||||||
|
['text', 'ajax_url', '异步请求地址', "如请求的地址是 <code>url('ajax/getCity')</code>,那么只需填写 <code>ajax/getCity</code>,或者直接填写以 <code>http</code>开头的url地址"],
|
||||||
|
['text', 'next_items', '下一级联动下拉框的表单名', "与当前有关联的下级联动下拉框名,多个用逗号隔开,如:area,other"],
|
||||||
|
['text', 'param', '请求参数名', "联动下拉框请求参数名,默认为配置名称"],
|
||||||
|
['text', 'level', '级别', '如果类型为【快速联动下拉框】则表示需要显示的级别数量,默认为2。如果类型为【百度地图】,则表示地图默认缩放级别,建议设置为12', 2],
|
||||||
|
['text', 'table', '表名', '要查询的表,里面必须含有id、name、pid三个字段,其中id和name字段可在下面重新定义'],
|
||||||
|
['text', 'pid', '父级id字段名', '即表中的父级ID字段名,如果表中的主键字段名为pid则可不填写'],
|
||||||
|
['text', 'key', '键字段名', '即表中的主键字段名,如果表中的主键字段名为id则可不填写'],
|
||||||
|
['text', 'option', '值字段名', '下拉菜单显示的字段名,如果表中的该字段名为name则可不填写'],
|
||||||
|
['text', 'ak', 'APPKEY', '百度编辑器APPKEY'],
|
||||||
|
['text', 'format', '格式'],
|
||||||
|
['textarea', 'tips', '字段说明', '字段补充说明'],
|
||||||
|
['radio', 'fixed', '是否为固定字段', '如果为 <code>固定字段</code> 则添加后不可修改', ['否', '是'], 0],
|
||||||
|
['radio', 'show', '是否显示', '新增或编辑时是否显示该字段', ['否', '是'], 1],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1],
|
||||||
|
['text', 'sort', '排序', '', 100],
|
||||||
|
])
|
||||||
|
->setTrigger('type', 'linkage', 'ajax_url,next_items,param')
|
||||||
|
->setTrigger('type', 'linkages', 'table,pid,key,option')
|
||||||
|
->setTrigger('type', 'bmap', 'ak')
|
||||||
|
->setTrigger('type', 'linkages,bmap', 'level')
|
||||||
|
->setTrigger('type', 'masked,date,time,datetime', 'format')
|
||||||
|
->setTrigger('type', 'checkbox,radio,array,select,linkage,linkages', 'options')
|
||||||
|
->js('field')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑字段
|
||||||
|
* @param null $id 字段id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function edit($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('参数错误');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Field');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
// 如果是快速联动
|
||||||
|
if ($data['type'] == 'linkages') {
|
||||||
|
$data['key'] = $data['key'] == '' ? 'id' : $data['key'];
|
||||||
|
$data['pid'] = $data['pid'] == '' ? 'pid' : $data['pid'];
|
||||||
|
$data['level'] = $data['level'] == '' ? '2' : $data['level'];
|
||||||
|
$data['option'] = $data['option'] == '' ? 'name' : $data['option'];
|
||||||
|
}
|
||||||
|
// 如果是百度地图
|
||||||
|
if ($data['type'] == 'bmap') {
|
||||||
|
$data['level'] = !$data['level'] ? 12 : $data['level'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新字段信息
|
||||||
|
$FieldModel = new FieldModel();
|
||||||
|
if ($FieldModel->updateField($data)) {
|
||||||
|
if ($FieldModel->isUpdate(true)->save($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('field_edit', 'cms_field', $id, UID, $data['name']);
|
||||||
|
$this->success('字段更新成功', cookie('__forward__'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->error('字段更新失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
$info = FieldModel::get($id);
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['hidden', 'model'],
|
||||||
|
['text', 'name', '字段名称', '由小写英文字母和下划线组成'],
|
||||||
|
['text', 'title', '字段标题', '可填写中文'],
|
||||||
|
['select', 'type', '字段类型', '', config('form_item_type')],
|
||||||
|
['text', 'define', '字段定义', '可根据实际需求自行填写或修改,但必须是正确的sql语法'],
|
||||||
|
['text', 'value', '字段默认值'],
|
||||||
|
['textarea', 'options', '额外选项', '用于单选、多选、下拉、联动等类型'],
|
||||||
|
['text', 'ajax_url', '异步请求地址', "如请求的地址是 <code>url('ajax/getCity')</code>,那么只需填写 <code>ajax/getCity</code>,或者直接填写以 <code>http</code>开头的url地址"],
|
||||||
|
['text', 'next_items', '下一级联动下拉框的表单名', "与当前有关联的下级联动下拉框名,多个用逗号隔开,如:area,other"],
|
||||||
|
['text', 'param', '请求参数名', "联动下拉框请求参数名,默认为配置名称"],
|
||||||
|
['text', 'level', '级别', '如果类型为【快速联动下拉框】则表示需要显示的级别数量,默认为2。如果类型为【百度地图】,则表示地图默认缩放级别,建议设置为12'],
|
||||||
|
['text', 'table', '表名', '要查询的表,里面必须含有id、name、pid三个字段,其中id和name字段可在下面重新定义'],
|
||||||
|
['text', 'pid', '父级id字段名', '即表中的父级ID字段名,如果表中的主键字段名为pid则可不填写'],
|
||||||
|
['text', 'key', '键字段名', '即表中的主键字段名,如果表中的主键字段名为id则可不填写'],
|
||||||
|
['text', 'option', '值字段名', '下拉菜单显示的字段名,如果表中的该字段名为name则可不填写'],
|
||||||
|
['text', 'ak', 'APPKEY', '百度编辑器APPKEY'],
|
||||||
|
['text', 'format', '格式'],
|
||||||
|
['textarea', 'tips', '字段说明', '字段补充说明'],
|
||||||
|
['radio', 'show', '是否显示', '新增或编辑时是否显示该字段', ['否', '是']],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']],
|
||||||
|
['text', 'sort', '排序'],
|
||||||
|
])
|
||||||
|
->setTrigger('type', 'linkage', 'ajax_url,next_items,param')
|
||||||
|
->setTrigger('type', 'linkages', 'table,pid,key,option')
|
||||||
|
->setTrigger('type', 'bmap', 'ak')
|
||||||
|
->setTrigger('type', 'linkages,bmap', 'level')
|
||||||
|
->setTrigger('type', 'masked,date,time,datetime', 'format')
|
||||||
|
->setTrigger('type', 'checkbox,radio,array,select,linkage,linkages', 'options')
|
||||||
|
->js('field')
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除字段
|
||||||
|
* @param null $ids 字段id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function delete($ids = null)
|
||||||
|
{
|
||||||
|
if ($ids === null) $this->error('参数错误');
|
||||||
|
|
||||||
|
$FieldModel = new FieldModel();
|
||||||
|
$field = $FieldModel->where('id', $ids)->find();
|
||||||
|
|
||||||
|
if ($FieldModel->deleteField($field)) {
|
||||||
|
if ($FieldModel->where('id', $ids)->delete()) {
|
||||||
|
// 记录行为
|
||||||
|
$details = '详情:文档模型('.get_model_title($field['model']).')、字段名称('.$field['name'].')、字段标题('.$field['title'].')、字段类型('.$field['type'].')';
|
||||||
|
action_log('field_delete', 'cms_field', $ids, UID, $details);
|
||||||
|
$this->success('删除成功', cookie('__forward__'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->error('删除失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用字段
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用字段
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置字段状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$field_delete = is_array($ids) ? '' : $ids;
|
||||||
|
$field_names = FieldModel::where('id', 'in', $ids)->column('name');
|
||||||
|
return parent::setStatus($type, ['field_'.$type, 'cms_field', $field_delete, UID, implode('、', $field_names)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$config = FieldModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $config . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['field_edit', 'cms_field', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
27
application/cms/admin/Index.php
Normal file
27
application/cms/admin/Index.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仪表盘控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Index extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 首页
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$this->assign('document', Db::name('cms_document')->where('trash', 0)->count());
|
||||||
|
$this->assign('column', Db::name('cms_column')->count());
|
||||||
|
$this->assign('page', Db::name('cms_page')->count());
|
||||||
|
$this->assign('model', Db::name('cms_model')->count());
|
||||||
|
$this->assign('page_title', '仪表盘');
|
||||||
|
return $this->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
}
|
208
application/cms/admin/Link.php
Normal file
208
application/cms/admin/Link.php
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Link as LinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 友情链接控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Link extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 友情链接列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = LinkModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['title', '标题', 'text.edit'],
|
||||||
|
['url', '链接', 'text.edit'],
|
||||||
|
['type', '类型', 'text', '', [1 => '文字链接', 2 => '图片链接']],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('add,enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons(['edit', 'delete' => ['data-tips' => '删除后无法恢复。']]) // 批量添加右侧按钮
|
||||||
|
->addOrder('id,title,type,create_time,update_time')
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->addValidate('Link', 'title,url')
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Link');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($link = LinkModel::create($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('link_add', 'cms_link', $link['id'], UID, $data['title']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['radio', 'type', '链接类型', '', [1 => '文字链接', 2 => '图片链接'], 1],
|
||||||
|
['text', 'title', '链接标题'],
|
||||||
|
['text', 'url', '链接地址', '请以 <code>http</code> 或 <code>https</code>开头'],
|
||||||
|
['image', 'logo', '链接LOGO'],
|
||||||
|
['tags', 'keywords', '关键词'],
|
||||||
|
['textarea', 'contact', '联系方式'],
|
||||||
|
['text', 'sort', '排序', '', 100],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->setTrigger('type', 2, 'logo')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param null $id 链接id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Link');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (LinkModel::update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('link_edit', 'cms_link', $id, UID, $data['title']);
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = LinkModel::get($id);
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['radio', 'type', '链接类型', '', [1 => '文字链接', 2 => '图片链接']],
|
||||||
|
['text', 'title', '链接标题'],
|
||||||
|
['text', 'url', '链接地址', '请以 <code>http</code> 或 <code>https</code>开头'],
|
||||||
|
['image', 'logo', '链接LOGO'],
|
||||||
|
['tags', 'keywords', '关键词'],
|
||||||
|
['textarea', 'contact', '联系方式'],
|
||||||
|
['text', 'sort', '排序'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']]
|
||||||
|
])
|
||||||
|
->setTrigger('type', 2, 'logo')
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除友情链接
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用友情链接
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用友情链接
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置友情链接状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$link_title = LinkModel::where('id', 'in', $ids)->column('title');
|
||||||
|
return parent::setStatus($type, ['link_'.$type, 'cms_link', 0, UID, implode('、', $link_title)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$link = LinkModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $link . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['link_edit', 'cms_link', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
255
application/cms/admin/Menu.php
Normal file
255
application/cms/admin/Menu.php
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Menu as MenuModel;
|
||||||
|
use app\cms\model\Column as ColumnModel;
|
||||||
|
use app\cms\model\Page as PageModel;
|
||||||
|
use util\Tree;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜单控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Menu extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 菜单列表
|
||||||
|
* @param null $id 导航id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
|
||||||
|
// 数据列表
|
||||||
|
$data_list = Db::view('cms_menu', true)
|
||||||
|
->view('cms_column', ['name' => 'column_name'], 'cms_menu.column=cms_column.id', 'left')
|
||||||
|
->view('cms_page', ['title' => 'page_title'], 'cms_menu.page=cms_page.id', 'left')
|
||||||
|
->where('cms_menu.nid', $id)
|
||||||
|
->order('cms_menu.sort,cms_menu.pid,cms_menu.id')
|
||||||
|
->select();
|
||||||
|
|
||||||
|
foreach ($data_list as &$item) {
|
||||||
|
if ($item['type'] == 0) {
|
||||||
|
$item['title'] = $item['column_name'];
|
||||||
|
} elseif ($item['type'] == 1) {
|
||||||
|
$item['title'] = $item['page_title'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($map)) {
|
||||||
|
$data_list = Tree::toList($data_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
$btnAdd = ['icon' => 'fa fa-plus', 'title' => '新增子菜单', 'href' => url('add', ['nid' => $id, 'pid' => '__id__'])];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['cms_menu.title|cms_column.name|cms_page.title' => '标题'])// 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['title', '标题', 'callback', function($value, $data){
|
||||||
|
return isset($data['title_prefix']) ? $data['title_display'] : $value;
|
||||||
|
}, '__data__'],
|
||||||
|
['type', '类型', 'text', '', ['栏目链接', '单页链接', '自定义链接']],
|
||||||
|
['target', '打开方式', 'select', ['_self' => '当前窗口', '_blank' => '新窗口']],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButton('back', ['href' => url('nav/index')])
|
||||||
|
->addTopButton('add', ['href' => url('add', ['nid' => $id])])
|
||||||
|
->addTopButtons('enable,disable')// 批量添加顶部按钮
|
||||||
|
->addRightButton('custom', $btnAdd)
|
||||||
|
->addRightButton('edit')
|
||||||
|
->addRightButton('delete', ['data-tips' => '删除后无法恢复。'])// 批量添加右侧按钮
|
||||||
|
->setRowList($data_list)// 设置表格数据
|
||||||
|
->addValidate('Nav', 'title')
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @param null $nid 导航id
|
||||||
|
* @param int $pid 菜单父级id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add($nid = null, $pid = 0)
|
||||||
|
{
|
||||||
|
if ($nid === null) $this->error('缺少参数');
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Menu');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($menu = MenuModel::create($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('menu_add', 'cms_menu', $menu['id'], UID, $data['title']);
|
||||||
|
$this->success('新增成功', url('index', ['id' => $nid]));
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'nid', $nid],
|
||||||
|
['hidden', 'pid', $pid],
|
||||||
|
['radio', 'type', '类型', '', ['栏目链接', '单页链接', '自定义链接'], 0],
|
||||||
|
['select', 'column', '栏目', '<code>必选</code>', ColumnModel::getTreeList(0, false)],
|
||||||
|
['select', 'page', '单页', '<code>必选</code>', PageModel::getTitleList()],
|
||||||
|
['text', 'title', '菜单标题', '<code>必填</code>,只用于区分'],
|
||||||
|
['text', 'url', 'URL', "<code>必填</code>。如果是模块链接,请填写<code>模块/控制器/操作</code>,如:<code>admin/menu/add</code>。如果是普通链接,则直接填写url地址,如:<code>http://www.dolphinphp.com</code>"],
|
||||||
|
['text', 'css', 'CSS类', '可选'],
|
||||||
|
['text', 'rel', '链接关系网(XFN)', '可选,即链接的rel值'],
|
||||||
|
['radio', 'target', '打开方式', '', ['_self' => '当前窗口', '_blank' => '新窗口'], '_self'],
|
||||||
|
['text', 'sort', '排序', '', 100],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->setTrigger('type', '0', 'column')
|
||||||
|
->setTrigger('type', '1', 'page')
|
||||||
|
->setTrigger('type', '2', 'title,url')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param null $id 菜单id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Menu');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (MenuModel::update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('menu_edit', 'cms_menu', $id, UID, $data['title']);
|
||||||
|
$this->success('编辑成功', url('index', ['id' => $data['nid']]));
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['hidden', 'nid'],
|
||||||
|
['radio', 'type', '类型', '', ['栏目链接', '单页链接', '自定义链接']],
|
||||||
|
['select', 'column', '栏目', '<code>必选</code>', ColumnModel::getTreeList(0, false)],
|
||||||
|
['select', 'page', '单页', '<code>必选</code>', PageModel::getTitleList()],
|
||||||
|
['text', 'title', '菜单标题', '<code>必填</code>,只用于区分'],
|
||||||
|
['text', 'url', 'URL', "<code>必填</code>。如果是模块链接,请填写<code>模块/控制器/操作</code>,如:<code>admin/menu/add</code>。如果是普通链接,则直接填写url地址,如:<code>http://www.dolphinphp.com</code>"],
|
||||||
|
['text', 'css', 'CSS类', '可选'],
|
||||||
|
['text', 'rel', '链接关系网(XFN)', '可选,即链接的rel值'],
|
||||||
|
['radio', 'target', '打开方式', '', ['_self' => '当前窗口', '_blank' => '新窗口'], '_self'],
|
||||||
|
['text', 'sort', '排序', '', 100],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->setFormData(MenuModel::get($id))
|
||||||
|
->setTrigger('type', '0', 'column')
|
||||||
|
->setTrigger('type', '1', 'page')
|
||||||
|
->setTrigger('type', '2', 'title,url')
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除菜单
|
||||||
|
* @param null $ids 菜单id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($ids = null)
|
||||||
|
{
|
||||||
|
// 检查是否有子菜单
|
||||||
|
if (MenuModel::where('pid', $ids)->find()) {
|
||||||
|
$this->error('请先删除或移动该菜单下的子菜单');
|
||||||
|
}
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用菜单
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用菜单
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置菜单状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$menu_title = MenuModel::where('id', 'in', $ids)->column('title');
|
||||||
|
return parent::setStatus($type, ['menu_'.$type, 'cms_menu', 0, UID, implode('、', $menu_title)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$menu = MenuModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $menu . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['menu_edit', 'cms_menu', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
228
application/cms/admin/Model.php
Normal file
228
application/cms/admin/Model.php
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Model as DocumentModel;
|
||||||
|
use app\admin\model\Menu as MenuModel;
|
||||||
|
use think\Db;
|
||||||
|
use think\facade\Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容模型控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Model extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 内容模型列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 数据列表
|
||||||
|
$data_list = DocumentModel::where($map)->order('sort,id desc')->paginate();
|
||||||
|
|
||||||
|
// 字段管理按钮
|
||||||
|
$btnField = [
|
||||||
|
'title' => '字段管理',
|
||||||
|
'icon' => 'fa fa-fw fa-navicon',
|
||||||
|
'href' => url('field/index', ['id' => '__id__'])
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['name' => '标识', 'title' => '标题']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['icon', '图标', 'icon'],
|
||||||
|
['title', '标题'],
|
||||||
|
['name', '标识'],
|
||||||
|
['table', '附加表'],
|
||||||
|
['type', '模型', 'text', '', ['系统', '普通', '独立']],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addFilter('type', ['系统', '普通', '独立'])
|
||||||
|
->addTopButtons('add,enable,disable') // 批量添加顶部按钮
|
||||||
|
->addRightButtons(['edit', 'custom' => $btnField, 'delete' => ['data-tips' => '删除模型将同时删除该模型下的所有字段,且无法恢复。']]) // 批量添加右侧按钮
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增内容模型
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
if ($data['table'] == '') {
|
||||||
|
$data['table'] = config('database.prefix') . 'cms_document_' . $data['name'];
|
||||||
|
} else {
|
||||||
|
$data['table'] = str_replace('#@__', config('database.prefix'), $data['table']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Model');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
// 严格验证附加表是否存在
|
||||||
|
if (table_exist($data['table'])) {
|
||||||
|
$this->error('附加表已存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($model = DocumentModel::create($data)) {
|
||||||
|
// 创建附加表
|
||||||
|
if (false === DocumentModel::createTable($model)) {
|
||||||
|
$this->error('创建附加表失败');
|
||||||
|
}
|
||||||
|
// 创建菜单节点
|
||||||
|
$map = [
|
||||||
|
'module' => 'cms',
|
||||||
|
'title' => '内容管理'
|
||||||
|
];
|
||||||
|
$menu_data = [
|
||||||
|
"module" => "cms",
|
||||||
|
"pid" => Db::name('admin_menu')->where($map)->value('id'),
|
||||||
|
"title" => $data['title'],
|
||||||
|
"url_type" => "module_admin",
|
||||||
|
"url_value" => "cms/content/{$data['name']}",
|
||||||
|
"url_target" => "_self",
|
||||||
|
"icon" => "fa fa-fw fa-list",
|
||||||
|
"online_hide" => "0",
|
||||||
|
"sort" => "100",
|
||||||
|
];
|
||||||
|
MenuModel::create($menu_data);
|
||||||
|
|
||||||
|
// 记录行为
|
||||||
|
action_log('model_add', 'cms_model', $model['id'], UID, $data['title']);
|
||||||
|
Cache::clear();
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$type_tips = '此选项添加后不可更改。如果为 <code>系统模型</code> 将禁止删除,对于 <code>独立模型</code>,将强制创建字段id,cid,uid,model,title,create_time,update_time,sort,status,trash,view';
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['text', 'name', '模型标识', '由小写字母、数字或下划线组成,不能以数字开头'],
|
||||||
|
['text', 'title', '模型标题', '可填写中文'],
|
||||||
|
['text', 'table', '附加表', '创建后不可更改。由小写字母、数字或下划线组成,如果不填写默认为 <code>'. config('database.prefix') . 'cms_document_模型标识</code>,如果需要自定义,请务必填写系统表前缀,<code>#@__</code>表示当前系统表前缀'],
|
||||||
|
['radio', 'type', '模型类别', $type_tips, ['系统模型', '普通模型', '独立模型(不使用主表)'], 1],
|
||||||
|
['icon', 'icon', '图标'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1],
|
||||||
|
['text', 'sort', '排序', '', 100],
|
||||||
|
])
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑内容模型
|
||||||
|
* @param null $id 模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null) {
|
||||||
|
if ($id === null) $this->error('参数错误');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Model.edit');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (DocumentModel::update($data)) {
|
||||||
|
cache('cms_model_list', null);
|
||||||
|
cache('cms_model_title_list', null);
|
||||||
|
// 记录行为
|
||||||
|
action_log('model_edit', 'cms_model', $id, UID, "ID({$id}),标题({$data['title']})");
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$list_model_type = ['系统模型', '普通模型', '独立模型(不使用主表)'];
|
||||||
|
|
||||||
|
// 模型信息
|
||||||
|
$info = DocumentModel::get($id);
|
||||||
|
$info['type'] = $list_model_type[$info['type']];
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['hidden', 'name'],
|
||||||
|
['static', 'name', '模型标识'],
|
||||||
|
['static', 'type', '模型类别'],
|
||||||
|
['static', 'table', '附加表'],
|
||||||
|
['text', 'title', '模型标题', '可填写中文'],
|
||||||
|
['icon', 'icon', '图标'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']],
|
||||||
|
['text', 'sort', '排序'],
|
||||||
|
])
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除内容模型
|
||||||
|
* @param null $ids 内容模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($ids = null)
|
||||||
|
{
|
||||||
|
if ($ids === null) $this->error('参数错误');
|
||||||
|
|
||||||
|
$model = DocumentModel::where('id', $ids)->find();
|
||||||
|
if ($model['type'] == 0) {
|
||||||
|
$this->error('禁止删除系统模型');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除表和字段信息
|
||||||
|
if (DocumentModel::deleteTable($ids)) {
|
||||||
|
// 删除主表中的文档
|
||||||
|
if (false === Db::name('cms_document')->where('model', $ids)->delete()) {
|
||||||
|
$this->error('删除主表文档失败');
|
||||||
|
}
|
||||||
|
// 删除菜单节点
|
||||||
|
$map = [
|
||||||
|
'module' => 'cms',
|
||||||
|
'url_value' => "cms/content/{$model['name']}"
|
||||||
|
];
|
||||||
|
if (false === Db::name('admin_menu')->where($map)->delete()) {
|
||||||
|
$this->error('删除菜单节点失败');
|
||||||
|
}
|
||||||
|
// 删除字段数据
|
||||||
|
if (false !== Db::name('cms_field')->where('model', $ids)->delete()) {
|
||||||
|
cache('cms_model_list', null);
|
||||||
|
cache('cms_model_title_list', null);
|
||||||
|
return parent::delete();
|
||||||
|
} else {
|
||||||
|
$this->error('删除内容模型字段失败');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error('删除内容模型表失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
167
application/cms/admin/Nav.php
Normal file
167
application/cms/admin/Nav.php
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Nav as NavModel;
|
||||||
|
use app\cms\model\Menu as MenuModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导航控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Nav extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 导航列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = NavModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
// 自定义按钮
|
||||||
|
$btnMenuList = [
|
||||||
|
'title' => '菜单列表',
|
||||||
|
'icon' => 'fa fa-list',
|
||||||
|
'href' => url('menu/index', ['id' => '__id__'])
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题'])// 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['tag', '标识', 'text.edit'],
|
||||||
|
['title', '标题', 'text.edit'],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('add,enable,disable,delete')// 批量添加顶部按钮
|
||||||
|
->addRightButton('custom', $btnMenuList)
|
||||||
|
->addRightButton('delete', ['data-tips' => '删除后无法恢复。'])// 批量添加右侧按钮
|
||||||
|
->addOrder('id,title,create_time,update_time')
|
||||||
|
->setRowList($data_list)// 设置表格数据
|
||||||
|
->addValidate('Nav', 'tag,title')
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Nav');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($nav = NavModel::create($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('nav_add', 'cms_nav', $nav['id'], UID, $data['title']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['text', 'tag', '菜单标识', '由字母和下划线组成,如:main_nav'],
|
||||||
|
['text', 'title', '菜单标题', '必填'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除导航
|
||||||
|
* @param null $ids 菜单id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($ids = null)
|
||||||
|
{
|
||||||
|
if ($ids === null) $this->error('参数错误');
|
||||||
|
// 删除该导航的所有子菜单
|
||||||
|
if (false === MenuModel::where('nid', 'in', $ids)->delete()) {
|
||||||
|
$this->error('删除失败');
|
||||||
|
}
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用导航
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用导航
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置导航状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$nav_title = NavModel::where('id', 'in', $ids)->column('title');
|
||||||
|
return parent::setStatus($type, ['nav_'.$type, 'cms_nav', 0, UID, implode('、', $nav_title)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$nav = NavModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $nav . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['nav_edit', 'cms_nav', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
204
application/cms/admin/Page.php
Normal file
204
application/cms/admin/Page.php
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Page as PageModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单页控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Page extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 单页列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder();
|
||||||
|
// 数据列表
|
||||||
|
$data_list = PageModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['title', '标题', 'text.edit'],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('add,enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons(['edit', 'delete' => ['data-tips' => '删除后无法恢复。']]) // 批量添加右侧按钮
|
||||||
|
->addOrder('id,title,create_time,update_time')
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->addValidate('Page', 'title')
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Page');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($page = PageModel::create($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('page_add', 'cms_page', $page['id'], UID, $data['title']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['text', 'title', '页面标题'],
|
||||||
|
['tags', 'keywords', '页面关键词', '关键字之间用英文逗号隔开'],
|
||||||
|
['textarea', 'description', '页面描述', '100字左右'],
|
||||||
|
['text', 'template', '模板文件名'],
|
||||||
|
['ckeditor', 'content', '页面内容'],
|
||||||
|
['image', 'cover', '单页封面'],
|
||||||
|
['text', 'view', '阅读量', '', 0],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param null $id 单页id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Page');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (PageModel::update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('page_edit', 'cms_page', $id, UID, $data['title']);
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = PageModel::get($id);
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['text', 'title', '页面标题'],
|
||||||
|
['tags', 'keywords', '页面关键词', '关键字之间用英文逗号隔开'],
|
||||||
|
['textarea', 'description', '页面描述', '100字左右'],
|
||||||
|
['text', 'template', '模板文件名'],
|
||||||
|
['ckeditor', 'content', '页面内容'],
|
||||||
|
['image', 'cover', '单页封面'],
|
||||||
|
['text', 'view', '阅读量', '', 0],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']]
|
||||||
|
])
|
||||||
|
->setFormdata($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除单页
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用单页
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用单页
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置单页状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$page_title = PageModel::where('id', 'in', $ids)->column('title');
|
||||||
|
return parent::setStatus($type, ['page_'.$type, 'cms_page', 0, UID, implode('、', $page_title)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$page = PageModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $page . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['page_edit', 'cms_page', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
194
application/cms/admin/Recycle.php
Normal file
194
application/cms/admin/Recycle.php
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Document as DocumentModel;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回收站控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Recycle extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 文档列表
|
||||||
|
* @param string $model 内容模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index($model = '')
|
||||||
|
{
|
||||||
|
if ($model == '') {
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
$map[] = ['cms_document.trash', '=', 1];
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = DocumentModel::getList($map, $order);
|
||||||
|
|
||||||
|
// 自定义按钮
|
||||||
|
$btnRestore = [
|
||||||
|
'class' => 'btn btn-xs btn-default ajax-get confirm',
|
||||||
|
'icon' => 'fa fa-fw fa-reply',
|
||||||
|
'title' => '还原',
|
||||||
|
'href' => url('restore', ['ids' => '__id__'])
|
||||||
|
];
|
||||||
|
$btnRestoreAll = [
|
||||||
|
'class' => 'btn btn-success ajax-post confirm',
|
||||||
|
'icon' => 'fa fa-fw fa-reply-all',
|
||||||
|
'title' => '批量还原',
|
||||||
|
'href' => url('restore')
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题', 'cms_column.name' => '栏目名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['title', '标题'],
|
||||||
|
['column_name', '栏目名称'],
|
||||||
|
['view', '点击量'],
|
||||||
|
['username', '发布人'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButton('enable', $btnRestoreAll) // 批量添加顶部按钮
|
||||||
|
->addTopButton('delete', ['title' => '批量删除', 'href' => url('delete'), 'data-tips' => '删除后不可回复!']) // 批量添加顶部按钮
|
||||||
|
->addRightButton('custom', $btnRestore) // 添加右侧按钮
|
||||||
|
->addRightButton('delete', ['href' => url('delete', ['ids' => '__id__']), 'data-tips' => '删除后不可回复!']) // 添加右侧按钮
|
||||||
|
->addOrder('id,title,column_name,view,username,update_time')
|
||||||
|
->addFilter(['column_name' => 'cms_column.name', 'username' => 'admin_user'])
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
} else {
|
||||||
|
$table_name = get_model_table($model);
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
$map[] = ['trash', '=', 1];
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder('update_time desc');
|
||||||
|
// 数据列表
|
||||||
|
$data_list = Db::view($table_name, true)
|
||||||
|
->view("cms_column", ['name' => 'column_name'], 'cms_column.id='.$table_name.'.cid', 'left')
|
||||||
|
->view("admin_user", 'username', 'admin_user.id='.$table_name.'.uid', 'left')
|
||||||
|
->where($map)
|
||||||
|
->order($order)
|
||||||
|
->paginate();
|
||||||
|
|
||||||
|
// 自定义按钮
|
||||||
|
$btnRestore = [
|
||||||
|
'class' => 'btn btn-xs btn-default ajax-get confirm',
|
||||||
|
'icon' => 'fa fa-fw fa-reply',
|
||||||
|
'title' => '还原',
|
||||||
|
'href' => url('restore', ['table' => $table_name, 'ids' => '__id__'])
|
||||||
|
];
|
||||||
|
$btnRestoreAll = [
|
||||||
|
'class' => 'btn btn-success ajax-post confirm',
|
||||||
|
'icon' => 'fa fa-fw fa-reply-all',
|
||||||
|
'title' => '批量还原',
|
||||||
|
'href' => url('restore', ['table' => $table_name])
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题', 'cms_column.name' => '栏目名称']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['title', '标题'],
|
||||||
|
['column_name', '栏目名称'],
|
||||||
|
['view', '点击量'],
|
||||||
|
['username', '发布人'],
|
||||||
|
['update_time', '更新时间', 'datetime'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButton('enable', $btnRestoreAll) // 添加顶部按钮
|
||||||
|
->addTopButton('delete', ['title' => '批量删除', 'href' => url('delete', ['table' => $table_name]), 'data-tips' => '删除后不可回复!']) // 添加顶部按钮
|
||||||
|
->addRightButton('custom', $btnRestore) // 添加右侧按钮
|
||||||
|
->addRightButton('delete', ['href' => url('delete', ['ids' => '__id__', 'table' => $table_name]), 'data-tips' => '删除后不可回复!']) // 添加右侧按钮
|
||||||
|
->addOrder('id,title,column_name,view,username,update_time')
|
||||||
|
->addFilter(['column_name' => 'cms_column.name', 'username' => 'admin_user'])
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 还原文档
|
||||||
|
* @param null $ids 文档id
|
||||||
|
* @param string $table 表名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
public function restore($ids = null, $table = '')
|
||||||
|
{
|
||||||
|
if ($ids === null) $this->error('请选择要操作的数据');
|
||||||
|
$table = $table != '' ? substr($table, strlen(config('database.prefix'))) : 'cms_document';
|
||||||
|
|
||||||
|
$document_id = is_array($ids) ? '' : $ids;
|
||||||
|
$document_title = Db::name($table)->where('id', 'in', $ids)->column('title');
|
||||||
|
|
||||||
|
// 还原文档
|
||||||
|
if (false === Db::name($table)->where('id', 'in', $ids)->setField('trash', 0)) {
|
||||||
|
$this->error('还原失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除并记录日志
|
||||||
|
action_log('document_restore', $table, $document_id, UID, implode('、', $document_title));
|
||||||
|
$this->success('还原成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 彻底删除文档
|
||||||
|
* @param null $ids 文档id
|
||||||
|
* @param string $table 表名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($ids = null, $table = '')
|
||||||
|
{
|
||||||
|
if ($ids === null) $this->error('请选择要操作的数据');
|
||||||
|
$ids = is_array($ids) ? $ids : (array)$ids;
|
||||||
|
|
||||||
|
if ($table == '') {
|
||||||
|
// 获取文档标题和模型id
|
||||||
|
$data_list = Db::name('cms_document')->where('id', 'in', $ids)->column('id,model,title');
|
||||||
|
|
||||||
|
foreach ($data_list as $document) {
|
||||||
|
// 附加表名
|
||||||
|
$extra_table = get_model_table($document['model']);
|
||||||
|
|
||||||
|
// 删除附加表文档
|
||||||
|
if (false === Db::table($extra_table)->where('aid', $document['id'])->delete()) {
|
||||||
|
$this->error('删除文档:'. $document['title']. ' 失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除主表文档
|
||||||
|
if (false === Db::name('cms_document')->where('id', $document['id'])->delete()) {
|
||||||
|
$this->error('删除失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录行为
|
||||||
|
action_log('document_delete', 'cms_document', $document['id'], UID, $document['title']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 文档标题
|
||||||
|
$document_title = Db::table($table)->where('id', 'in', $ids)->column('title');
|
||||||
|
|
||||||
|
// 删除独立文档
|
||||||
|
if (false === Db::table($table)->where('id', 'in', $ids)->delete()) {
|
||||||
|
$this->error('删除失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录行为
|
||||||
|
action_log('document_delete', $table, 0, UID, '表('.$table.'),文档('.implode('、', $document_title).')');
|
||||||
|
}
|
||||||
|
$this->success('删除成功');
|
||||||
|
}
|
||||||
|
}
|
200
application/cms/admin/Slider.php
Normal file
200
application/cms/admin/Slider.php
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Slider as SliderModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 滚动图片控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Slider extends Admin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 滚动图片列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder();
|
||||||
|
// 数据列表
|
||||||
|
$data_list = SliderModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setSearch(['title' => '标题']) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['cover', '图片', 'picture'],
|
||||||
|
['title', '标题', 'text.edit'],
|
||||||
|
['url', '链接', 'text.edit'],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('add,enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons(['edit', 'delete' => ['data-tips' => '删除后无法恢复。']]) // 批量添加右侧按钮
|
||||||
|
->addOrder('id,title,create_time')
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->addValidate('Slider', 'title,url')
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Slider');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($slider = SliderModel::create($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('slider_add', 'cms_slider', $slider['id'], UID, $data['title']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['text', 'title', '标题'],
|
||||||
|
['image', 'cover', '图片'],
|
||||||
|
['text', 'url', '链接'],
|
||||||
|
['text', 'sort', '排序', '', 100],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param null $id 滚动图片id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Slider');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (SliderModel::update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('slider_add', 'cms_slider', $id, UID, $data['title']);
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = SliderModel::get($id);
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['text', 'title', '标题'],
|
||||||
|
['image', 'cover', '图片'],
|
||||||
|
['text', 'url', '链接'],
|
||||||
|
['text', 'sort', '排序'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']]
|
||||||
|
])
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除单页
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用单页
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用单页
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置单页状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$slider_title = SliderModel::where('id', 'in', $ids)->column('title');
|
||||||
|
return parent::setStatus($type, ['slider_'.$type, 'cms_slider', 0, UID, implode('、', $slider_title)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$slider = SliderModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $slider . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['slider_edit', 'cms_slider', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
212
application/cms/admin/Support.php
Normal file
212
application/cms/admin/Support.php
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\admin;
|
||||||
|
|
||||||
|
use app\admin\controller\Admin;
|
||||||
|
use app\common\builder\ZBuilder;
|
||||||
|
use app\cms\model\Support as SupportModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客服控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Support extends Admin
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// 查询
|
||||||
|
$map = $this->getMap();
|
||||||
|
// 排序
|
||||||
|
$order = $this->getOrder();
|
||||||
|
// 数据列表
|
||||||
|
$data_list = SupportModel::where($map)->order($order)->paginate();
|
||||||
|
|
||||||
|
$search = [
|
||||||
|
'name' => '客服名称',
|
||||||
|
'qq' => 'QQ',
|
||||||
|
'msn' => 'MSN',
|
||||||
|
'taobao' => '淘宝旺旺',
|
||||||
|
'alibaba' => '阿里旺旺',
|
||||||
|
'skype' => 'SKYPE'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用ZBuilder快速创建数据表格
|
||||||
|
return ZBuilder::make('table')
|
||||||
|
->setPageTips('添加的QQ需要到【shang.qq.com】登录后在【商家沟通组建—设置】开启QQ的在线状态,否则将显示“未启用”<br>开启和关闭在线客服功能,以及更多设置,请在 <a class="alert-link link-effect" href="'.url('admin/system/index', ['group' => 'cms']).'">系统设置</a> 中操作。')
|
||||||
|
->setSearch($search) // 设置搜索框
|
||||||
|
->addColumns([ // 批量添加数据列
|
||||||
|
['id', 'ID'],
|
||||||
|
['name', '客服名称', 'text.edit'],
|
||||||
|
['qq', 'QQ'],
|
||||||
|
['msn', 'MSN'],
|
||||||
|
['taobao', '淘宝旺旺'],
|
||||||
|
['alibaba', '阿里旺旺'],
|
||||||
|
['skype', 'SKYPE'],
|
||||||
|
['create_time', '创建时间', 'datetime'],
|
||||||
|
['sort', '排序', 'text.edit'],
|
||||||
|
['status', '状态', 'switch'],
|
||||||
|
['right_button', '操作', 'btn']
|
||||||
|
])
|
||||||
|
->addTopButtons('add,enable,disable,delete') // 批量添加顶部按钮
|
||||||
|
->addRightButtons(['edit', 'delete' => ['data-tips' => '删除后无法恢复。']]) // 批量添加右侧按钮
|
||||||
|
->addOrder('id,name,create_time,update_time')
|
||||||
|
->addValidate('Support', 'name')
|
||||||
|
->setRowList($data_list) // 设置表格数据
|
||||||
|
->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Support');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if ($support = SupportModel::create($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('support_add', 'cms_support', $support['id'], UID, $data['name']);
|
||||||
|
$this->success('新增成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('新增失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示添加页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['text', 'name', '客服名称'],
|
||||||
|
['text', 'qq', 'QQ号码'],
|
||||||
|
['text', 'msn', 'MSN号码'],
|
||||||
|
['text', 'taobao', '淘宝旺旺'],
|
||||||
|
['text', 'alibaba', '阿里旺旺'],
|
||||||
|
['text', 'skype', 'SKYPE'],
|
||||||
|
['text', 'sort', '排序', '', 100],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是'], 1]
|
||||||
|
])
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* @param null $id 客服id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
*/
|
||||||
|
public function edit($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
// 表单数据
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 验证
|
||||||
|
$result = $this->validate($data, 'Support');
|
||||||
|
if(true !== $result) $this->error($result);
|
||||||
|
|
||||||
|
if (SupportModel::update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('support_edit', 'cms_support', $id, UID, $data['name']);
|
||||||
|
$this->success('编辑成功', 'index');
|
||||||
|
} else {
|
||||||
|
$this->error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = SupportModel::get($id);
|
||||||
|
|
||||||
|
// 显示编辑页面
|
||||||
|
return ZBuilder::make('form')
|
||||||
|
->addFormItems([
|
||||||
|
['hidden', 'id'],
|
||||||
|
['text', 'name', '客服名称'],
|
||||||
|
['text', 'qq', 'QQ号码'],
|
||||||
|
['text', 'msn', 'MSN号码'],
|
||||||
|
['text', 'taobao', '淘宝旺旺'],
|
||||||
|
['text', 'alibaba', '阿里旺旺'],
|
||||||
|
['text', 'skype', 'SKYPE'],
|
||||||
|
['text', 'sort', '排序'],
|
||||||
|
['radio', 'status', '立即启用', '', ['否', '是']]
|
||||||
|
])
|
||||||
|
->setFormData($info)
|
||||||
|
->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除客服
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function delete($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用客服
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function enable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('enable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用客服
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function disable($record = [])
|
||||||
|
{
|
||||||
|
return $this->setStatus('disable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置客服状态:删除、禁用、启用
|
||||||
|
* @param string $type 类型:delete/enable/disable
|
||||||
|
* @param array $record
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function setStatus($type = '', $record = [])
|
||||||
|
{
|
||||||
|
$ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
|
||||||
|
$support_title = SupportModel::where('id', 'in', $ids)->column('name');
|
||||||
|
return parent::setStatus($type, ['support_'.$type, 'cms_support', 0, UID, implode('、', $support_title)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速编辑
|
||||||
|
* @param array $record 行为日志
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function quickEdit($record = [])
|
||||||
|
{
|
||||||
|
$id = input('post.pk', '');
|
||||||
|
$field = input('post.name', '');
|
||||||
|
$value = input('post.value', '');
|
||||||
|
$support = SupportModel::where('id', $id)->value($field);
|
||||||
|
$details = '字段(' . $field . '),原值(' . $support . '),新值:(' . $value . ')';
|
||||||
|
return parent::quickEdit(['support_edit', 'cms_support', $id, UID, $details]);
|
||||||
|
}
|
||||||
|
}
|
158
application/cms/common.php
Normal file
158
application/cms/common.php
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 门户模块公共函数库
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
if (!function_exists('get_column_name')) {
|
||||||
|
/**
|
||||||
|
* 获取栏目名称
|
||||||
|
* @param int $cid 栏目id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function get_column_name($cid = 0)
|
||||||
|
{
|
||||||
|
$column_list = model('cms/column')->getList();
|
||||||
|
return isset($column_list[$cid]) ? $column_list[$cid]['name'] : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_model_name')) {
|
||||||
|
/**
|
||||||
|
* 获取内容模型名称
|
||||||
|
* @param string $id 内容模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function get_model_name($id = '')
|
||||||
|
{
|
||||||
|
$model_list = model('cms/model')->getList();
|
||||||
|
return isset($model_list[$id]) ? $model_list[$id]['name'] : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_model_title')) {
|
||||||
|
/**
|
||||||
|
* 获取内容模型标题
|
||||||
|
* @param string $id 内容模型标题
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function get_model_title($id = '')
|
||||||
|
{
|
||||||
|
$model_list = model('cms/model')->getList();
|
||||||
|
return isset($model_list[$id]) ? $model_list[$id]['title'] : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_model_type')) {
|
||||||
|
/**
|
||||||
|
* 获取内容模型类别:0-系统,1-普通,2-独立
|
||||||
|
* @param int $id 模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function get_model_type($id = 0)
|
||||||
|
{
|
||||||
|
$model_list = model('cms/model')->getList();
|
||||||
|
return isset($model_list[$id]) ? $model_list[$id]['type'] : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('get_model_table')) {
|
||||||
|
/**
|
||||||
|
* 获取内容模型附加表名
|
||||||
|
* @param int $id 模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function get_model_table($id = 0)
|
||||||
|
{
|
||||||
|
$model_list = model('cms/model')->getList();
|
||||||
|
return isset($model_list[$id]) ? $model_list[$id]['table'] : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('is_default_field')) {
|
||||||
|
/**
|
||||||
|
* 检查是否为系统默认字段
|
||||||
|
* @param string $field 字段名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function is_default_field($field = '')
|
||||||
|
{
|
||||||
|
$system_fields = cache('cms_system_fields');
|
||||||
|
if (!$system_fields) {
|
||||||
|
$system_fields = Db::name('cms_field')->where('model', 0)->column('name');
|
||||||
|
cache('cms_system_fields', $system_fields);
|
||||||
|
}
|
||||||
|
return in_array($field, $system_fields, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('table_exist')) {
|
||||||
|
/**
|
||||||
|
* 检查附加表是否存在
|
||||||
|
* @param string $table_name 附加表名
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function table_exist($table_name = '')
|
||||||
|
{
|
||||||
|
return true == Db::query("SHOW TABLES LIKE '{$table_name}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('time_tran')) {
|
||||||
|
/**
|
||||||
|
* 转换时间
|
||||||
|
* @param int $timer 时间戳
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function time_tran($timer)
|
||||||
|
{
|
||||||
|
$diff = $_SERVER['REQUEST_TIME'] - $timer;
|
||||||
|
$day = floor($diff / 86400);
|
||||||
|
$free = $diff % 86400;
|
||||||
|
if ($day > 0) {
|
||||||
|
return $day . " 天前";
|
||||||
|
} else {
|
||||||
|
if ($free > 0) {
|
||||||
|
$hour = floor($free / 3600);
|
||||||
|
$free = $free % 3600;
|
||||||
|
if ($hour > 0) {
|
||||||
|
return $hour . " 小时前";
|
||||||
|
} else {
|
||||||
|
if ($free > 0) {
|
||||||
|
$min = floor($free / 60);
|
||||||
|
$free = $free % 60;
|
||||||
|
if ($min > 0) {
|
||||||
|
return $min . " 分钟前";
|
||||||
|
} else {
|
||||||
|
if ($free > 0) {
|
||||||
|
return $free . " 秒前";
|
||||||
|
} else {
|
||||||
|
return '刚刚';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return '刚刚';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return '刚刚';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
97
application/cms/home/Column.php
Normal file
97
application/cms/home/Column.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\home;
|
||||||
|
|
||||||
|
use app\cms\model\Column as ColumnModel;
|
||||||
|
use think\Db;
|
||||||
|
use util\Tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前台栏目文档列表控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Column extends Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 栏目文章列表
|
||||||
|
* @param null $id 栏目id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index($id = null)
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
$map = [
|
||||||
|
'status' => 1,
|
||||||
|
'id' => $id
|
||||||
|
];
|
||||||
|
|
||||||
|
$column = Db::name('cms_column')->where($map)->find();
|
||||||
|
if (!$column) $this->error('该栏目不存在');
|
||||||
|
|
||||||
|
$model = Db::name('cms_model')->where('id', $column['model'])->find();
|
||||||
|
|
||||||
|
if ($model['type'] == 2) {
|
||||||
|
$cid_all = ColumnModel::getChildsId($id);
|
||||||
|
$cid_all[] = (int)$id;
|
||||||
|
|
||||||
|
$map = [
|
||||||
|
[$model['table'].'.trash', '=', 0],
|
||||||
|
[$model['table'].'.status', '=', 1],
|
||||||
|
[$model['table'].'.cid', 'in', $cid_all],
|
||||||
|
];
|
||||||
|
|
||||||
|
$data_list = Db::view($model['table'], true)
|
||||||
|
->view('admin_user', 'username', $model['table'].'.uid=admin_user.id', 'left')
|
||||||
|
->where($map)
|
||||||
|
->order('create_time desc')
|
||||||
|
->paginate(config('list_rows'));
|
||||||
|
$this->assign('model', $column['model']);
|
||||||
|
} else {
|
||||||
|
$cid_all = ColumnModel::getChildsId($id);
|
||||||
|
$cid_all[] = (int)$id;
|
||||||
|
|
||||||
|
$map = [
|
||||||
|
['cms_document.trash', '=', 0],
|
||||||
|
['cms_document.status', '=', 1],
|
||||||
|
['cms_document.cid', 'in', $cid_all],
|
||||||
|
];
|
||||||
|
|
||||||
|
$data_list = Db::view('cms_document', true)
|
||||||
|
->view('admin_user', 'username', 'cms_document.uid=admin_user.id', 'left')
|
||||||
|
->view($model['table'], '*', 'cms_document.id='. $model['table'] . '.aid', 'left')
|
||||||
|
->where($map)
|
||||||
|
->order('create_time desc')
|
||||||
|
->paginate(config('list_rows'));
|
||||||
|
$this->assign('model', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assign('lists', $data_list);
|
||||||
|
$this->assign('pages', $data_list->render());
|
||||||
|
$this->assign('breadcrumb', $this->getBreadcrumb($id));
|
||||||
|
$this->assign('column_info', $column);
|
||||||
|
|
||||||
|
$template = $column['list_template'] == '' ? 'list' : substr($column['list_template'], 0, strpos($column['list_template'], '.'));
|
||||||
|
return $this->fetch($template);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取栏目面包屑导航
|
||||||
|
* @param $id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getBreadcrumb($id)
|
||||||
|
{
|
||||||
|
$columns = ColumnModel::where('status', 1)->column('id,pid,name,url,target,type');
|
||||||
|
foreach ($columns as &$column) {
|
||||||
|
if ($column['type'] == 0) {
|
||||||
|
$column['url'] = url('cms/column/index', ['id' => $column['id']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Tree::config(['title' => 'name'])->getParents($columns, $id);
|
||||||
|
}
|
||||||
|
}
|
82
application/cms/home/Common.php
Normal file
82
application/cms/home/Common.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\home;
|
||||||
|
|
||||||
|
use app\index\controller\Home;
|
||||||
|
use think\Db;
|
||||||
|
use util\Tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前台公共控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Common extends Home
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 初始化方法
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
protected function initialize()
|
||||||
|
{
|
||||||
|
parent::initialize();
|
||||||
|
|
||||||
|
// 获取菜单
|
||||||
|
$this->getNav();
|
||||||
|
// 获取滚动图片
|
||||||
|
$this->assign('slider', $this->getSlider());
|
||||||
|
// 获取客服
|
||||||
|
$this->assign('support', $this->getSupport());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取导航
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function getNav()
|
||||||
|
{
|
||||||
|
$list_nav = Db::name('cms_nav')->where('status', 1)->column('id,tag');
|
||||||
|
|
||||||
|
foreach ($list_nav as $id => $tag) {
|
||||||
|
$data_list = Db::view('cms_menu', true)
|
||||||
|
->view('cms_column', ['name' => 'column_name'], 'cms_menu.column=cms_column.id', 'left')
|
||||||
|
->view('cms_page', ['title' => 'page_title'], 'cms_menu.page=cms_page.id', 'left')
|
||||||
|
->where('cms_menu.nid', $id)
|
||||||
|
->where('cms_menu.status', 1)
|
||||||
|
->order('cms_menu.sort,cms_menu.pid,cms_menu.id')
|
||||||
|
->select();
|
||||||
|
|
||||||
|
foreach ($data_list as &$item) {
|
||||||
|
if ($item['type'] == 0) { // 栏目链接
|
||||||
|
$item['title'] = $item['column_name'];
|
||||||
|
$item['url'] = url('cms/column/index', ['id' => $item['column']]);
|
||||||
|
} elseif ($item['type'] == 1) { // 单页链接
|
||||||
|
$item['title'] = $item['page_title'];
|
||||||
|
$item['url'] = url('cms/page/detail', ['id' => $item['page']]);
|
||||||
|
} else {
|
||||||
|
if ($item['url'] != '#' && substr($item['url'], 0, 4) != 'http') {
|
||||||
|
$item['url'] = url($item['url']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assign($tag, Tree::toLayer($data_list));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取滚动图片
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function getSlider()
|
||||||
|
{
|
||||||
|
return Db::name('cms_slider')->where('status', 1)->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取在线客服
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
private function getSupport()
|
||||||
|
{
|
||||||
|
return Db::name('cms_support')->where('status', 1)->order('sort')->select();
|
||||||
|
}
|
||||||
|
}
|
144
application/cms/home/Document.php
Normal file
144
application/cms/home/Document.php
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\home;
|
||||||
|
|
||||||
|
use app\cms\model\Column as ColumnModel;
|
||||||
|
use app\cms\model\Document as DocumentModel;
|
||||||
|
use util\Tree;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档控制器
|
||||||
|
* @package app\cms\home
|
||||||
|
*/
|
||||||
|
class Document extends Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 文档详情页
|
||||||
|
* @param null $id 文档id
|
||||||
|
* @param string $model 独立模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function detail($id = null, $model = '')
|
||||||
|
{
|
||||||
|
if ($id === null) $this->error('缺少参数');
|
||||||
|
|
||||||
|
if ($model != '') {
|
||||||
|
$table = get_model_table($model);
|
||||||
|
$map = [
|
||||||
|
$table.'.status' => 1,
|
||||||
|
$table.'.trash' => 0
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$map = [
|
||||||
|
'cms_document.status' => 1,
|
||||||
|
'cms_document.trash' => 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = DocumentModel::getOne($id, $model, $map);
|
||||||
|
if (isset($info['tags'])) {
|
||||||
|
$info['tags'] = explode(',', $info['tags']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assign('document', $info);
|
||||||
|
$this->assign('breadcrumb', $this->getBreadcrumb($info['cid']));
|
||||||
|
$this->assign('prev', $this->getPrev($id, $model));
|
||||||
|
$this->assign('next', $this->getNext($id, $model));
|
||||||
|
|
||||||
|
$template = $info['detail_template'] == '' ? 'detail' : substr($info['detail_template'], 0, strpos($info['detail_template'], '.'));
|
||||||
|
return $this->fetch($template);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取栏目面包屑导航
|
||||||
|
* @param int $id 栏目id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function getBreadcrumb($id)
|
||||||
|
{
|
||||||
|
$columns = ColumnModel::where('status', 1)->column('id,pid,name,url,target,type');
|
||||||
|
foreach ($columns as &$column) {
|
||||||
|
if ($column['type'] == 0) {
|
||||||
|
$column['url'] = url('cms/column/index', ['id' => $column['id']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Tree::config(['title' => 'name'])->getParents($columns, $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上一篇文档
|
||||||
|
* @param int $id 当前文档id
|
||||||
|
* @param string $model 独立模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|string|\think\Model|null
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
private function getPrev($id, $model = '')
|
||||||
|
{
|
||||||
|
if ($model == '') {
|
||||||
|
$cid = Db::name('cms_document')->where('id', $id)->value('cid');
|
||||||
|
$document = Db::name('cms_document')->where([
|
||||||
|
['status', '=', 1],
|
||||||
|
['trash', '=', 0],
|
||||||
|
['cid', '=', $cid],
|
||||||
|
['id', 'lt', $id]
|
||||||
|
])->order('id desc')->find();
|
||||||
|
} else {
|
||||||
|
$table = get_model_table($model);
|
||||||
|
$cid = Db::table($table)->where('id', $id)->value('cid');
|
||||||
|
$document = Db::table($table)->where([
|
||||||
|
['status', '=', 1],
|
||||||
|
['trash', '=', 0],
|
||||||
|
['cid', '=', $cid],
|
||||||
|
['id', 'lt', $id]
|
||||||
|
])->order('id desc')->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($document) {
|
||||||
|
$document['url'] = url('cms/document/detail', ['id' => $document['id'], 'model' => $model]);
|
||||||
|
}
|
||||||
|
return $document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取下一篇文档
|
||||||
|
* @param int $id 当前文档id
|
||||||
|
* @param string $model 独立模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|string|\think\Model|null
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
private function getNext($id, $model = '')
|
||||||
|
{
|
||||||
|
if ($model == '') {
|
||||||
|
$cid = Db::name('cms_document')->where('id', $id)->value('cid');
|
||||||
|
$document = Db::name('cms_document')->where([
|
||||||
|
['status', '=', 1],
|
||||||
|
['trash', '=', 0],
|
||||||
|
['cid', '=', $cid],
|
||||||
|
['id', 'gt', $id]
|
||||||
|
])->find();
|
||||||
|
} else {
|
||||||
|
$table = get_model_table($model);
|
||||||
|
$cid = Db::table($table)->where('id', $id)->value('cid');
|
||||||
|
$document = Db::table($table)->where([
|
||||||
|
['status', '=', 1],
|
||||||
|
['trash', '=', 0],
|
||||||
|
['cid', '=', $cid],
|
||||||
|
['id', 'gt', $id]
|
||||||
|
])->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($document) {
|
||||||
|
$document['url'] = url('cms/document/detail', ['id' => $document['id'], 'model' => $model]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $document;
|
||||||
|
}
|
||||||
|
}
|
19
application/cms/home/Index.php
Normal file
19
application/cms/home/Index.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\home;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前台首页控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Index extends Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 首页
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return $this->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
}
|
34
application/cms/home/Page.php
Normal file
34
application/cms/home/Page.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\home;
|
||||||
|
|
||||||
|
use app\cms\model\Page as PageModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前台单页控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Page extends Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 单页详情
|
||||||
|
* @param null $id 单页id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function detail($id = null)
|
||||||
|
{
|
||||||
|
$info = PageModel::where('status', 1)->find($id);
|
||||||
|
$info['url'] = url('cms/page/detail', ['id' => $info['id']]);
|
||||||
|
$info['tags'] = explode(',', $info['keywords']);
|
||||||
|
|
||||||
|
// 更新阅读量
|
||||||
|
PageModel::where('id', $id)->setInc('view');
|
||||||
|
|
||||||
|
$this->assign('page_info', $info);
|
||||||
|
return $this->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
}
|
40
application/cms/home/Search.php
Normal file
40
application/cms/home/Search.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\home;
|
||||||
|
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前台搜索控制器
|
||||||
|
* @package app\cms\admin
|
||||||
|
*/
|
||||||
|
class Search extends Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 搜索列表
|
||||||
|
* @param string $keyword 关键词
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public function index($keyword = '')
|
||||||
|
{
|
||||||
|
if ($keyword == '') $this->error('请输入关键字');
|
||||||
|
$map = [
|
||||||
|
['cms_document.trash', '=', 0],
|
||||||
|
['cms_document.status', '=', 1],
|
||||||
|
['cms_document.title', 'like', "%$keyword%"]
|
||||||
|
];
|
||||||
|
|
||||||
|
$data_list = Db::view('cms_document', true)
|
||||||
|
->view('admin_user', 'username', 'cms_document.uid=admin_user.id', 'left')
|
||||||
|
->where($map)
|
||||||
|
->order('create_time desc')
|
||||||
|
->paginate(config('list_rows'));
|
||||||
|
|
||||||
|
$this->assign('keyword', $keyword);
|
||||||
|
$this->assign('lists', $data_list);
|
||||||
|
$this->assign('pages', $data_list->render());
|
||||||
|
|
||||||
|
return $this->fetch(); // 渲染模板
|
||||||
|
}
|
||||||
|
}
|
604
application/cms/info.php
Normal file
604
application/cms/info.php
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模块信息
|
||||||
|
*/
|
||||||
|
return [
|
||||||
|
// 模块名[必填]
|
||||||
|
'name' => 'cms',
|
||||||
|
// 模块标题[必填]
|
||||||
|
'title' => '门户',
|
||||||
|
// 模块唯一标识[必填],格式:模块名.开发者标识.module
|
||||||
|
'identifier' => 'cms.ming.module',
|
||||||
|
// 模块图标[选填]
|
||||||
|
'icon' => 'fa fa-fw fa-newspaper-o',
|
||||||
|
// 模块描述[选填]
|
||||||
|
'description' => '门户模块',
|
||||||
|
// 开发者[必填]
|
||||||
|
'author' => 'CaiWeiMing',
|
||||||
|
// 开发者网址[选填]
|
||||||
|
'author_url' => 'http://www.dolphinphp.com',
|
||||||
|
// 版本[必填],格式采用三段式:主版本号.次版本号.修订版本号
|
||||||
|
'version' => '1.0.0',
|
||||||
|
// 模块依赖[可选],格式[[模块名, 模块唯一标识, 依赖版本, 对比方式]]
|
||||||
|
'need_module' => [
|
||||||
|
['admin', 'admin.dolphinphp.module', '1.0.0']
|
||||||
|
],
|
||||||
|
// 插件依赖[可选],格式[[插件名, 插件唯一标识, 依赖版本, 对比方式]]
|
||||||
|
'need_plugin' => [],
|
||||||
|
// 数据表[有数据库表时必填]
|
||||||
|
'tables' => [
|
||||||
|
'cms_advert',
|
||||||
|
'cms_advert_type',
|
||||||
|
'cms_column',
|
||||||
|
'cms_document',
|
||||||
|
'cms_document_article',
|
||||||
|
'cms_field',
|
||||||
|
'cms_link',
|
||||||
|
'cms_menu',
|
||||||
|
'cms_model',
|
||||||
|
'cms_nav',
|
||||||
|
'cms_page',
|
||||||
|
'cms_slider',
|
||||||
|
'cms_support',
|
||||||
|
],
|
||||||
|
// 原始数据库表前缀
|
||||||
|
// 用于在导入模块sql时,将原有的表前缀转换成系统的表前缀
|
||||||
|
// 一般模块自带sql文件时才需要配置
|
||||||
|
'database_prefix' => 'dp_',
|
||||||
|
|
||||||
|
// 模块参数配置
|
||||||
|
'config' => [
|
||||||
|
['text', 'summary', '默认摘要字数', '发布文章时,如果没有填写摘要,则自动获取文档内容为摘要。如果此处不填写或填写0,则不提取摘要。', 0],
|
||||||
|
['ckeditor', 'contact', '联系方式', '', '<div class="font-s13 push"><strong>河源市卓锐科技有限公司</strong><br />
|
||||||
|
地址:河源市江东新区东环路汇通苑D3-H232<br />
|
||||||
|
电话:0762-8910006<br />
|
||||||
|
邮箱:admin@zrthink.com</div>'],
|
||||||
|
['textarea', 'meta_head', '顶部代码', '代码会放在 <code></head></code> 标签以上'],
|
||||||
|
['textarea', 'meta_foot', '底部代码', '代码会放在 <code></body></code> 标签以上'],
|
||||||
|
['radio', 'support_status', '在线客服', '', ['禁用', '启用'], 1],
|
||||||
|
['colorpicker', 'support_color', '在线客服配色', '', 'rgba(0,158,232,1)'],
|
||||||
|
['image', 'support_wx', '在线客服微信二维码', '在线客服微信二维码'],
|
||||||
|
['ckeditor', 'support_extra', '在线客服额外内容', '在线客服额外内容,可填写电话或其他说明'],
|
||||||
|
],
|
||||||
|
|
||||||
|
// 行为配置
|
||||||
|
'action' => [
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'slider_delete',
|
||||||
|
'title' => '删除滚动图片',
|
||||||
|
'remark' => '删除滚动图片',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了滚动图片:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'slider_edit',
|
||||||
|
'title' => '编辑滚动图片',
|
||||||
|
'remark' => '编辑滚动图片',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了滚动图片:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'slider_add',
|
||||||
|
'title' => '添加滚动图片',
|
||||||
|
'remark' => '添加滚动图片',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了滚动图片:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'document_delete',
|
||||||
|
'title' => '删除文档',
|
||||||
|
'remark' => '删除文档',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了文档:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'document_restore',
|
||||||
|
'title' => '还原文档',
|
||||||
|
'remark' => '还原文档',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 还原了文档:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'nav_disable',
|
||||||
|
'title' => '禁用导航',
|
||||||
|
'remark' => '禁用导航',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了导航:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'nav_enable',
|
||||||
|
'title' => '启用导航',
|
||||||
|
'remark' => '启用导航',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了导航:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'nav_delete',
|
||||||
|
'title' => '删除导航',
|
||||||
|
'remark' => '删除导航',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了导航:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'nav_edit',
|
||||||
|
'title' => '编辑导航',
|
||||||
|
'remark' => '编辑导航',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了导航:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'nav_add',
|
||||||
|
'title' => '添加导航',
|
||||||
|
'remark' => '添加导航',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了导航:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'model_disable',
|
||||||
|
'title' => '禁用内容模型',
|
||||||
|
'remark' => '禁用内容模型',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了内容模型:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'model_enable',
|
||||||
|
'title' => '启用内容模型',
|
||||||
|
'remark' => '启用内容模型',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了内容模型:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'model_delete',
|
||||||
|
'title' => '删除内容模型',
|
||||||
|
'remark' => '删除内容模型',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了内容模型:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'model_edit',
|
||||||
|
'title' => '编辑内容模型',
|
||||||
|
'remark' => '编辑内容模型',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了内容模型:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'model_add',
|
||||||
|
'title' => '添加内容模型',
|
||||||
|
'remark' => '添加内容模型',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了内容模型:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'menu_disable',
|
||||||
|
'title' => '禁用导航菜单',
|
||||||
|
'remark' => '禁用导航菜单',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了导航菜单:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'menu_enable',
|
||||||
|
'title' => '启用导航菜单',
|
||||||
|
'remark' => '启用导航菜单',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了导航菜单:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'menu_delete',
|
||||||
|
'title' => '删除导航菜单',
|
||||||
|
'remark' => '删除导航菜单',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了导航菜单:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'menu_edit',
|
||||||
|
'title' => '编辑导航菜单',
|
||||||
|
'remark' => '编辑导航菜单',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了导航菜单:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'menu_add',
|
||||||
|
'title' => '添加导航菜单',
|
||||||
|
'remark' => '添加导航菜单',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了导航菜单:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'link_disable',
|
||||||
|
'title' => '禁用友情链接',
|
||||||
|
'remark' => '禁用友情链接',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了友情链接:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'link_enable',
|
||||||
|
'title' => '启用友情链接',
|
||||||
|
'remark' => '启用友情链接',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了友情链接:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'link_delete',
|
||||||
|
'title' => '删除友情链接',
|
||||||
|
'remark' => '删除友情链接',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了友情链接:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'link_edit',
|
||||||
|
'title' => '编辑友情链接',
|
||||||
|
'remark' => '编辑友情链接',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了友情链接:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'link_add',
|
||||||
|
'title' => '添加友情链接',
|
||||||
|
'remark' => '添加友情链接',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了友情链接:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'field_disable',
|
||||||
|
'title' => '禁用模型字段',
|
||||||
|
'remark' => '禁用模型字段',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了模型字段:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'field_enable',
|
||||||
|
'title' => '启用模型字段',
|
||||||
|
'remark' => '启用模型字段',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了模型字段:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'field_delete',
|
||||||
|
'title' => '删除模型字段',
|
||||||
|
'remark' => '删除模型字段',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了模型字段:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'field_edit',
|
||||||
|
'title' => '编辑模型字段',
|
||||||
|
'remark' => '编辑模型字段',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了模型字段:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'field_add',
|
||||||
|
'title' => '添加模型字段',
|
||||||
|
'remark' => '添加模型字段',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了模型字段:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'column_disable',
|
||||||
|
'title' => '禁用栏目',
|
||||||
|
'remark' => '禁用栏目',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了栏目:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'column_enable',
|
||||||
|
'title' => '启用栏目',
|
||||||
|
'remark' => '启用栏目',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了栏目:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'column_delete',
|
||||||
|
'title' => '删除栏目',
|
||||||
|
'remark' => '删除栏目',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了栏目:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'column_edit',
|
||||||
|
'title' => '编辑栏目',
|
||||||
|
'remark' => '编辑栏目',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了栏目:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'column_add',
|
||||||
|
'title' => '添加栏目',
|
||||||
|
'remark' => '添加栏目',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了栏目:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_type_disable',
|
||||||
|
'title' => '禁用广告分类',
|
||||||
|
'remark' => '禁用广告分类',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了广告分类:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_type_enable',
|
||||||
|
'title' => '启用广告分类',
|
||||||
|
'remark' => '启用广告分类',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了广告分类:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_type_delete',
|
||||||
|
'title' => '删除广告分类',
|
||||||
|
'remark' => '删除广告分类',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了广告分类:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_type_edit',
|
||||||
|
'title' => '编辑广告分类',
|
||||||
|
'remark' => '编辑广告分类',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了广告分类:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_type_add',
|
||||||
|
'title' => '添加广告分类',
|
||||||
|
'remark' => '添加广告分类',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了广告分类:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_disable',
|
||||||
|
'title' => '禁用广告',
|
||||||
|
'remark' => '禁用广告',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了广告:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_enable',
|
||||||
|
'title' => '启用广告',
|
||||||
|
'remark' => '启用广告',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了广告:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_delete',
|
||||||
|
'title' => '删除广告',
|
||||||
|
'remark' => '删除广告',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了广告:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_edit',
|
||||||
|
'title' => '编辑广告',
|
||||||
|
'remark' => '编辑广告',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了广告:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'advert_add',
|
||||||
|
'title' => '添加广告',
|
||||||
|
'remark' => '添加广告',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了广告:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'document_disable',
|
||||||
|
'title' => '禁用文档',
|
||||||
|
'remark' => '禁用文档',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了文档:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'document_enable',
|
||||||
|
'title' => '启用文档',
|
||||||
|
'remark' => '启用文档',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了文档:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'document_trash',
|
||||||
|
'title' => '回收文档',
|
||||||
|
'remark' => '回收文档',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 回收了文档:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'document_edit',
|
||||||
|
'title' => '编辑文档',
|
||||||
|
'remark' => '编辑文档',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了文档:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'document_add',
|
||||||
|
'title' => '添加文档',
|
||||||
|
'remark' => '添加文档',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了文档:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'slider_enable',
|
||||||
|
'title' => '启用滚动图片',
|
||||||
|
'remark' => '启用滚动图片',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了滚动图片:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'slider_disable',
|
||||||
|
'title' => '禁用滚动图片',
|
||||||
|
'remark' => '禁用滚动图片',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了滚动图片:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'support_add',
|
||||||
|
'title' => '添加客服',
|
||||||
|
'remark' => '添加客服',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 添加了客服:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'support_edit',
|
||||||
|
'title' => '编辑客服',
|
||||||
|
'remark' => '编辑客服',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 编辑了客服:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'support_delete',
|
||||||
|
'title' => '删除客服',
|
||||||
|
'remark' => '删除客服',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 删除了客服:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'support_enable',
|
||||||
|
'title' => '启用客服',
|
||||||
|
'remark' => '启用客服',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 启用了客服:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module' => 'cms',
|
||||||
|
'name' => 'support_disable',
|
||||||
|
'title' => '禁用客服',
|
||||||
|
'remark' => '禁用客服',
|
||||||
|
'rule' => '',
|
||||||
|
'log' => '[user|get_nickname] 禁用了客服:[details]',
|
||||||
|
'status' => 1,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
|
||||||
|
// 授权配置
|
||||||
|
'access' => [
|
||||||
|
'column' => [
|
||||||
|
'title' => '栏目授权',
|
||||||
|
'nodes' => [
|
||||||
|
'group' => 'column',
|
||||||
|
'table_name' => 'cms_column',
|
||||||
|
'primary_key' => 'id',
|
||||||
|
'parent_id' => 'pid',
|
||||||
|
'node_name' => 'name',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
888
application/cms/menus.php
Normal file
888
application/cms/menus.php
Normal file
@ -0,0 +1,888 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜单信息
|
||||||
|
*/
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'title' => '门户',
|
||||||
|
'icon' => 'fa fa-fw fa-newspaper-o',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/index/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '常用操作',
|
||||||
|
'icon' => 'fa fa-fw fa-folder-open-o',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => '',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '仪表盘',
|
||||||
|
'icon' => 'fa fa-fw fa-tachometer',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/index/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '发布文档',
|
||||||
|
'icon' => 'fa fa-fw fa-plus',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/document/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '文档列表',
|
||||||
|
'icon' => 'fa fa-fw fa-list',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/document/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/document/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/document/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/document/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/document/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/document/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '单页管理',
|
||||||
|
'icon' => 'fa fa-fw fa-file-word-o',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/page/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/page/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/page/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/page/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/page/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/page/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/page/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '回收站',
|
||||||
|
'icon' => 'fa fa-fw fa-recycle',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/recycle/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/recycle/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '还原',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/recycle/restore',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '内容管理',
|
||||||
|
'icon' => 'fa fa-fw fa-th-list',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => '',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '营销管理',
|
||||||
|
'icon' => 'fa fa-fw fa-money',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => '',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '广告管理',
|
||||||
|
'icon' => 'fa fa-fw fa-handshake-o',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '广告分类',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert_type/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert_type/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert_type/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert_type/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert_type/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert_type/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/advert_type/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '滚动图片',
|
||||||
|
'icon' => 'fa fa-fw fa-photo',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/slider/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/slider/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/slider/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/slider/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/slider/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/slider/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/slider/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '友情链接',
|
||||||
|
'icon' => 'fa fa-fw fa-link',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/link/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/link/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/link/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/link/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/link/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/link/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/link/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '客服管理',
|
||||||
|
'icon' => 'fa fa-fw fa-commenting',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/support/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/support/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/support/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/support/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/support/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/support/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/support/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '门户设置',
|
||||||
|
'icon' => 'fa fa-fw fa-sliders',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => '',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '栏目分类',
|
||||||
|
'icon' => 'fa fa-fw fa-sitemap',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/column/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 1,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/column/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/column/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/column/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/column/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/column/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/column/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '内容模型',
|
||||||
|
'icon' => 'fa fa-fw fa-th-large',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/model/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/model/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/model/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/model/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/model/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/model/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/model/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '字段管理',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/field/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/field/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/field/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/field/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/field/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/field/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/field/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '导航管理',
|
||||||
|
'icon' => 'fa fa-fw fa-map-signs',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/nav/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/nav/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/nav/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/nav/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/nav/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/nav/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/nav/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '菜单管理',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/menu/index',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
'child' => [
|
||||||
|
[
|
||||||
|
'title' => '新增',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/menu/add',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/menu/edit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '删除',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/menu/delete',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '启用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/menu/enable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '禁用',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/menu/disable',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => '快速编辑',
|
||||||
|
'icon' => '',
|
||||||
|
'url_type' => 'module_admin',
|
||||||
|
'url_value' => 'cms/menu/quickedit',
|
||||||
|
'url_target' => '_self',
|
||||||
|
'online_hide' => 0,
|
||||||
|
'sort' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
35
application/cms/model/Advert.php
Normal file
35
application/cms/model/Advert.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Advert extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_advert';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
// 定义修改器
|
||||||
|
public function setStartTimeAttr($value)
|
||||||
|
{
|
||||||
|
return $value != '' ? strtotime($value) : 0;
|
||||||
|
}
|
||||||
|
public function setEndTimeAttr($value)
|
||||||
|
{
|
||||||
|
return $value != '' ? strtotime($value) : 0;
|
||||||
|
}
|
||||||
|
public function getStartTimeAttr($value)
|
||||||
|
{
|
||||||
|
return $value != 0 ? date('Y-m-d', $value) : '';
|
||||||
|
}
|
||||||
|
public function getEndTimeAttr($value)
|
||||||
|
{
|
||||||
|
return $value != 0 ? date('Y-m-d', $value) : '';
|
||||||
|
}
|
||||||
|
}
|
17
application/cms/model/AdvertType.php
Normal file
17
application/cms/model/AdvertType.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告分类模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class AdvertType extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_advert_type';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
}
|
123
application/cms/model/Column.php
Normal file
123
application/cms/model/Column.php
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
use util\Tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 栏目模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Column extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_column';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题获取器
|
||||||
|
* @param $value
|
||||||
|
* @param $data
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
protected function getTitleAttr($value, $data) {
|
||||||
|
switch ($data['type']) {
|
||||||
|
case 0: // 栏目
|
||||||
|
break;
|
||||||
|
case 1: // 单页
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取栏目列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getList()
|
||||||
|
{
|
||||||
|
$data_list = cache('cms_column_list');
|
||||||
|
if (!$data_list) {
|
||||||
|
$data_list = self::where('status', 1)->column(true, 'id');
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('cms_column_list', $data_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取树状栏目
|
||||||
|
* @param int $id 需要隐藏的栏目id
|
||||||
|
* @param string $default 默认第一个节点项,默认为“顶级栏目”,如果为false则不显示,也可传入其他名称
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getTreeList($id = 0, $default = '')
|
||||||
|
{
|
||||||
|
$result[0] = '顶级栏目';
|
||||||
|
|
||||||
|
// 排除指定节点及其子节点
|
||||||
|
$where = [
|
||||||
|
['status', '=', 1]
|
||||||
|
];
|
||||||
|
if ($id !== 0) {
|
||||||
|
$hide_ids = array_merge([$id], self::getChildsId($id));
|
||||||
|
$where[] = ['id', 'not in', $hide_ids];
|
||||||
|
}
|
||||||
|
|
||||||
|
$data_list = Tree::config(['title' => 'name'])->toList(self::where($where)->order('pid,id')->column('id,pid,name'));
|
||||||
|
foreach ($data_list as $item) {
|
||||||
|
$result[$item['id']] = $item['title_display'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置默认节点项标题
|
||||||
|
if ($default != '') {
|
||||||
|
$result[0] = $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏默认节点项
|
||||||
|
if ($default === false) {
|
||||||
|
unset($result[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有子栏目id
|
||||||
|
* @param int $pid 父级id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getChildsId($pid = 0)
|
||||||
|
{
|
||||||
|
$ids = self::where('pid', $pid)->column('id');
|
||||||
|
foreach ($ids as $value) {
|
||||||
|
$ids = array_merge($ids, self::getChildsId($value));
|
||||||
|
}
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定栏目数据
|
||||||
|
* @param int $cid 栏目id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return mixed|static
|
||||||
|
*/
|
||||||
|
public static function getInfo($cid = 0)
|
||||||
|
{
|
||||||
|
$result = cache('cms_column_info_'. $cid);
|
||||||
|
if (!$result) {
|
||||||
|
$result = self::get($cid);
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('cms_column_info_'. $cid, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
213
application/cms/model/Document.php
Normal file
213
application/cms/model/Document.php
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
use think\Db;
|
||||||
|
use app\cms\model\Field as FieldModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Document extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_document';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文档列表
|
||||||
|
* @param array $map 筛选条件
|
||||||
|
* @param array $order 排序
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return \think\Paginator
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public static function getList($map = [], $order = [])
|
||||||
|
{
|
||||||
|
$data_list = self::view('cms_document', true)
|
||||||
|
->view("cms_column", ['name' => 'column_name'], 'cms_column.id=cms_document.cid', 'left')
|
||||||
|
->view("admin_user", 'username', 'admin_user.id=cms_document.uid', 'left')
|
||||||
|
->where($map)
|
||||||
|
->order($order)
|
||||||
|
->paginate();
|
||||||
|
return $data_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单篇文档
|
||||||
|
* @param string $id 文档id
|
||||||
|
* @param string $model 独立模型id
|
||||||
|
* @param array $map 查询条件
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|string|ThinkModel|null
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
*/
|
||||||
|
public static function getOne($id = '', $model = '', $map = [])
|
||||||
|
{
|
||||||
|
if ($model == '') {
|
||||||
|
$document = self::get($id);
|
||||||
|
$extra_table = get_model_table($document['model']);
|
||||||
|
|
||||||
|
$data = self::view('cms_document', true);
|
||||||
|
if ($extra_table != '') {
|
||||||
|
$data = $data->view($extra_table, true, 'cms_document.id='.$extra_table.'.aid', 'left');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data->view("cms_column", ['name' => 'column_name', 'list_template', 'detail_template'], 'cms_column.id=cms_document.cid', 'left')
|
||||||
|
->view("admin_user", 'username', 'admin_user.id=cms_document.uid', 'left')
|
||||||
|
->where('cms_document.id', $id)
|
||||||
|
->where($map)
|
||||||
|
->find();
|
||||||
|
} else {
|
||||||
|
$table = get_model_table($model);
|
||||||
|
return Db::view($table, true)
|
||||||
|
->view("cms_column", ['name' => 'column_name', 'list_template', 'detail_template'], 'cms_column.id='.$table.'.cid', 'left')
|
||||||
|
->where($table.'.id', $id)
|
||||||
|
->where($map)
|
||||||
|
->find();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增或更新文档
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
* @throws \think\Exception
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\exception\DbException
|
||||||
|
* @throws \think\exception\PDOException
|
||||||
|
*/
|
||||||
|
public function saveData()
|
||||||
|
{
|
||||||
|
$data = request()->post();
|
||||||
|
$data['uid'] = UID;
|
||||||
|
|
||||||
|
// 文档模型
|
||||||
|
$model = Db::name('cms_model')->where('id', $data['model'])->find();
|
||||||
|
|
||||||
|
if ($model['type'] != 2 && empty($data['summary']) && config('cms_config.summary') > 0) {
|
||||||
|
$data['summary'] = mb_substr(strip_tags($data['content']), 0, config('cms_config.summary'), 'utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理自定义属性
|
||||||
|
if (isset($data['flag'])) {
|
||||||
|
$data['flag'] = implode(',', $data['flag']);
|
||||||
|
} else {
|
||||||
|
$data['flag'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证基础内容
|
||||||
|
if ($data['title'] == '') {
|
||||||
|
$this->error = '标题不能为空';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理特殊字段类型
|
||||||
|
$fields = FieldModel::where('model', $data['model'])->where('status', 1)->column('name,type');
|
||||||
|
|
||||||
|
foreach ($fields as $name => $type) {
|
||||||
|
if (!isset($data[$name])) {
|
||||||
|
switch ($type) {
|
||||||
|
// 开关
|
||||||
|
case 'switch':
|
||||||
|
$data[$name] = 0;
|
||||||
|
break;
|
||||||
|
case 'checkbox':
|
||||||
|
$data[$name] = '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果值是数组则转换成字符串,适用于复选框等类型
|
||||||
|
if (is_array($data[$name])) {
|
||||||
|
$data[$name] = implode(',', $data[$name]);
|
||||||
|
}
|
||||||
|
switch ($type) {
|
||||||
|
// 开关
|
||||||
|
case 'switch':
|
||||||
|
$data[$name] = 1;
|
||||||
|
break;
|
||||||
|
// 日期时间
|
||||||
|
case 'date':
|
||||||
|
case 'time':
|
||||||
|
case 'datetime':
|
||||||
|
$data[$name] = strtotime($data[$name]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['id'])) {
|
||||||
|
if ($model['type'] == 2) {
|
||||||
|
// 新增独立模型文档
|
||||||
|
$data['create_time'] = request()->time();
|
||||||
|
$data['update_time'] = request()->time();
|
||||||
|
$insert_id = Db::table($model['table'])->insertGetId($data);
|
||||||
|
if (false === $insert_id) {
|
||||||
|
$this->error = '新增失败';
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// 记录行为
|
||||||
|
action_log('document_add', $model['table'], $insert_id, UID, $data['title']);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 新增文档基础内容
|
||||||
|
if ($document = self::create($data)) {
|
||||||
|
// 新增文档扩展内容
|
||||||
|
if ($model['table'] != '') {
|
||||||
|
$data['aid'] = $document['id'];
|
||||||
|
if (false === Db::table($model['table'])->insert($data)) {
|
||||||
|
// 删除已添加的基础内容
|
||||||
|
self::destroy($document['id']);
|
||||||
|
$this->error = '新增扩展内容出错';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 记录行为
|
||||||
|
action_log('document_add', 'cms_document', $document['id'], UID, $document['title']);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
$this->error = '新增基础内容出错';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 更新独立模型文档
|
||||||
|
if ($model['type'] == 2) {
|
||||||
|
// 新增独立模型文档
|
||||||
|
$data['update_time'] = request()->time();
|
||||||
|
if (false === Db::table($model['table'])->update($data)) {
|
||||||
|
$this->error = '编辑失败';
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// 记录行为
|
||||||
|
action_log('document_edit', $model['table'], $data['id'], UID, $data['title']);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 更新文档基础内容
|
||||||
|
if (self::update($data)) {
|
||||||
|
// 更新文档扩展内容
|
||||||
|
$data['aid'] = $data['id'];
|
||||||
|
if (false !== Db::table($model['table'])->update($data)) {
|
||||||
|
// 记录行为
|
||||||
|
action_log('document_edit', 'cms_document', $data['id'], UID, $data['title']);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
$this->error = '更新扩展内容出错';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error = '更新基础内容出错';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
140
application/cms/model/Field.php
Normal file
140
application/cms/model/Field.php
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Field extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_field';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
// 当前表名
|
||||||
|
protected $_table_name = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建字段
|
||||||
|
* @param null $field 字段数据
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function newField($field = null)
|
||||||
|
{
|
||||||
|
if ($field === null) {
|
||||||
|
$this->error = '缺少参数';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->tableExist($field['model'])) {
|
||||||
|
$sql = <<<EOF
|
||||||
|
ALTER TABLE `{$this->_table_name}`
|
||||||
|
ADD COLUMN `{$field['name']}` {$field['define']} COMMENT '{$field['title']}';
|
||||||
|
EOF;
|
||||||
|
} else {
|
||||||
|
$mdoel_title = get_model_title($field['model']);
|
||||||
|
|
||||||
|
// 新建普通扩展表
|
||||||
|
$sql = <<<EOF
|
||||||
|
CREATE TABLE IF NOT EXISTS `{$this->_table_name}` (
|
||||||
|
`aid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '文档id' ,
|
||||||
|
`{$field['name']}` {$field['define']} COMMENT '{$field['title']}' ,
|
||||||
|
PRIMARY KEY (`aid`)
|
||||||
|
)
|
||||||
|
ENGINE=MyISAM
|
||||||
|
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
|
||||||
|
CHECKSUM=0
|
||||||
|
ROW_FORMAT=DYNAMIC
|
||||||
|
DELAY_KEY_WRITE=0
|
||||||
|
COMMENT='{$mdoel_title}模型扩展表'
|
||||||
|
;
|
||||||
|
EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Db::execute($sql);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$this->error = '字段添加失败';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新字段
|
||||||
|
* @param null $field 字段数据
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function updateField($field = null)
|
||||||
|
{
|
||||||
|
if ($field === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取原字段名
|
||||||
|
$field_name = $this->where('id', $field['id'])->value('name');
|
||||||
|
|
||||||
|
if ($this->tableExist($field['model'])) {
|
||||||
|
$sql = <<<EOF
|
||||||
|
ALTER TABLE `{$this->_table_name}`
|
||||||
|
CHANGE COLUMN `{$field_name}` `{$field['name']}` {$field['define']} COMMENT '{$field['title']}';
|
||||||
|
EOF;
|
||||||
|
try {
|
||||||
|
Db::execute($sql);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除字段
|
||||||
|
* @param null $field 字段数据
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function deleteField($field = null)
|
||||||
|
{
|
||||||
|
if ($field === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->tableExist($field['model'])) {
|
||||||
|
$sql = <<<EOF
|
||||||
|
ALTER TABLE `{$this->_table_name}`
|
||||||
|
DROP COLUMN `{$field['name']}`;
|
||||||
|
EOF;
|
||||||
|
try {
|
||||||
|
Db::execute($sql);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查表是否存在
|
||||||
|
* @param string $model 文档模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function tableExist($model = '')
|
||||||
|
{
|
||||||
|
$this->_table_name = strtolower(get_model_table($model));
|
||||||
|
return true == Db::query("SHOW TABLES LIKE '{$this->_table_name}'");
|
||||||
|
}
|
||||||
|
}
|
17
application/cms/model/Link.php
Normal file
17
application/cms/model/Link.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 友情链接模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Link extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_link';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
}
|
17
application/cms/model/Menu.php
Normal file
17
application/cms/model/Menu.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜单模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Menu extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_menu';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
}
|
227
application/cms/model/Model.php
Normal file
227
application/cms/model/Model.php
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
use think\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Model extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_model';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取内容模型列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getList()
|
||||||
|
{
|
||||||
|
$data_list = cache('cms_model_list');
|
||||||
|
if (!$data_list) {
|
||||||
|
$data_list = self::where('status', 1)->column(true, 'id');
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('cms_model_list', $data_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取内容模型标题列表(只含id和title)
|
||||||
|
* @param array $map 筛选条件
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getTitleList($map = [])
|
||||||
|
{
|
||||||
|
return self::where('status', 1)->where($map)->column('id,title');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除附加表
|
||||||
|
* @param null $model 内容模型id
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function deleteTable($model = null)
|
||||||
|
{
|
||||||
|
if ($model === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$table_name = self::where('id', $model)->value('table');
|
||||||
|
return false !== Db::execute("DROP TABLE IF EXISTS `{$table_name}`");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建独立模型表
|
||||||
|
* @param mixed $data 模型数据
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function createTable($data)
|
||||||
|
{
|
||||||
|
if ($data['type'] == 2) {
|
||||||
|
// 新建独立扩展表
|
||||||
|
$sql = <<<EOF
|
||||||
|
CREATE TABLE IF NOT EXISTS `{$data['table']}` (
|
||||||
|
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '文档id' ,
|
||||||
|
`cid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '栏目id' ,
|
||||||
|
`uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户id' ,
|
||||||
|
`model` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '模型id' ,
|
||||||
|
`title` varchar(256) NOT NULL DEFAULT '' COMMENT '标题' ,
|
||||||
|
`create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间' ,
|
||||||
|
`update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间' ,
|
||||||
|
`sort` int(11) NOT NULL DEFAULT 100 COMMENT '排序' ,
|
||||||
|
`status` tinyint(2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '状态' ,
|
||||||
|
`view` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '点击量' ,
|
||||||
|
`trash` tinyint(2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '回收站' ,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
)
|
||||||
|
ENGINE=MyISAM
|
||||||
|
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
|
||||||
|
CHECKSUM=0
|
||||||
|
ROW_FORMAT=DYNAMIC
|
||||||
|
DELAY_KEY_WRITE=0
|
||||||
|
COMMENT='{$data['title']}模型表'
|
||||||
|
;
|
||||||
|
EOF;
|
||||||
|
} else {
|
||||||
|
// 新建普通扩展表
|
||||||
|
$sql = <<<EOF
|
||||||
|
CREATE TABLE IF NOT EXISTS `{$data['table']}` (
|
||||||
|
`aid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '文档id' ,
|
||||||
|
PRIMARY KEY (`aid`)
|
||||||
|
)
|
||||||
|
ENGINE=MyISAM
|
||||||
|
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
|
||||||
|
CHECKSUM=0
|
||||||
|
ROW_FORMAT=DYNAMIC
|
||||||
|
DELAY_KEY_WRITE=0
|
||||||
|
COMMENT='{$data['title']}模型扩展表'
|
||||||
|
;
|
||||||
|
EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Db::execute($sql);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data['type'] == 2) {
|
||||||
|
// 添加默认字段
|
||||||
|
$default = [
|
||||||
|
'model' => $data['id'],
|
||||||
|
'level' => '',
|
||||||
|
'create_time' => request()->time(),
|
||||||
|
'update_time' => request()->time(),
|
||||||
|
'status' => 1
|
||||||
|
];
|
||||||
|
$data = [
|
||||||
|
[
|
||||||
|
'name' => 'id',
|
||||||
|
'title' => '文档id',
|
||||||
|
'define' => 'int(11) UNSIGNED NOT NULL',
|
||||||
|
'type' => 'text',
|
||||||
|
'show' => 0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'cid',
|
||||||
|
'title' => '栏目',
|
||||||
|
'define' => 'int(11) UNSIGNED NOT NULL',
|
||||||
|
'type' => 'static',
|
||||||
|
'show' => 0,
|
||||||
|
'value' => 0,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'uid',
|
||||||
|
'title' => '用户id',
|
||||||
|
'define' => 'int(11) UNSIGNED NOT NULL',
|
||||||
|
'type' => 'text',
|
||||||
|
'show' => 0,
|
||||||
|
'value' => 0,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'model',
|
||||||
|
'title' => '文档模型',
|
||||||
|
'define' => 'int(11) UNSIGNED NOT NULL',
|
||||||
|
'type' => 'text',
|
||||||
|
'show' => 0,
|
||||||
|
'value' => 0,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'title',
|
||||||
|
'title' => '标题',
|
||||||
|
'define' => 'varchar(256) NOT NULL',
|
||||||
|
'type' => 'text',
|
||||||
|
'show' => 1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'create_time',
|
||||||
|
'title' => '创建时间',
|
||||||
|
'define' => 'int(11) UNSIGNED NOT NULL',
|
||||||
|
'type' => 'datetime',
|
||||||
|
'show' => 0,
|
||||||
|
'value' => 0,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'update_time',
|
||||||
|
'title' => '更新时间',
|
||||||
|
'define' => 'int(11) UNSIGNED NOT NULL',
|
||||||
|
'type' => 'datetime',
|
||||||
|
'show' => 0,
|
||||||
|
'value' => 0,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'sort',
|
||||||
|
'title' => '排序',
|
||||||
|
'define' => 'int(11) UNSIGNED NOT NULL',
|
||||||
|
'type' => 'text',
|
||||||
|
'show' => 1,
|
||||||
|
'value' => 100,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'status',
|
||||||
|
'title' => '状态',
|
||||||
|
'define' => 'tinyint(2) NOT NULL',
|
||||||
|
'type' => 'radio',
|
||||||
|
'show' => 1,
|
||||||
|
'value' => 1,
|
||||||
|
'options' => '0:禁用
|
||||||
|
1:启用'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'view',
|
||||||
|
'title' => '点击量',
|
||||||
|
'define' => 'int(11) UNSIGNED NOT NULL',
|
||||||
|
'type' => 'text',
|
||||||
|
'show' => 0,
|
||||||
|
'value' => 0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'trash',
|
||||||
|
'title' => '回收站',
|
||||||
|
'define' => 'tinyint(2) NOT NULL',
|
||||||
|
'type' => 'radio',
|
||||||
|
'show' => 0,
|
||||||
|
'value' => 0
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($data as $item) {
|
||||||
|
$item = array_merge($item, $default);
|
||||||
|
Db::name('cms_field')->insert($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
17
application/cms/model/Nav.php
Normal file
17
application/cms/model/Nav.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导航模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Nav extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_nav';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
}
|
35
application/cms/model/Page.php
Normal file
35
application/cms/model/Page.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单页模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Page extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_page';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单页标题列表
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public static function getTitleList()
|
||||||
|
{
|
||||||
|
$result = cache('cms_page_title_list');
|
||||||
|
if (!$result) {
|
||||||
|
$result = self::where('status', 1)->column('id,title');
|
||||||
|
// 非开发模式,缓存数据
|
||||||
|
if (config('develop_mode') == 0) {
|
||||||
|
cache('cms_page_title_list', $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
17
application/cms/model/Slider.php
Normal file
17
application/cms/model/Slider.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 滚动图片模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Slider extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_slider';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
}
|
17
application/cms/model/Support.php
Normal file
17
application/cms/model/Support.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace app\cms\model;
|
||||||
|
|
||||||
|
use think\Model as ThinkModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客服模型
|
||||||
|
* @package app\cms\model
|
||||||
|
*/
|
||||||
|
class Support extends ThinkModel
|
||||||
|
{
|
||||||
|
// 设置当前模型对应的完整数据表名称
|
||||||
|
protected $name = 'cms_support';
|
||||||
|
|
||||||
|
// 自动写入时间戳
|
||||||
|
protected $autoWriteTimestamp = true;
|
||||||
|
}
|
65
application/cms/public/static/cms/css/main.css
Normal file
65
application/cms/public/static/cms/css/main.css
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
body,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
.h1,
|
||||||
|
.h2,
|
||||||
|
.h3,
|
||||||
|
.h4,
|
||||||
|
.h5,
|
||||||
|
.h6,
|
||||||
|
.select2-container--default .select2-search--inline .select2-search__field{
|
||||||
|
font-family: "Microsoft Yahei", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
/* 单页 */
|
||||||
|
.document-content p img,
|
||||||
|
.page-content p img{
|
||||||
|
width: 100%!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 客服 */
|
||||||
|
.support {
|
||||||
|
position: fixed;
|
||||||
|
top: 200px;
|
||||||
|
right: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.support .support-tag{
|
||||||
|
width: 38px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 8px 10px;
|
||||||
|
float: left;
|
||||||
|
background-color: #009EE8;
|
||||||
|
color: #fff;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.support .support-content{
|
||||||
|
width: 200px;
|
||||||
|
float: right;
|
||||||
|
background: #009EE8;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.support .support-item{
|
||||||
|
padding: 5px 0;
|
||||||
|
border-bottom: 1px dotted #ccc;
|
||||||
|
}
|
||||||
|
.support .support-item a{
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
.support .support-content-inner{
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 8px;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
.support .support-wx img{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.support .support-extra{
|
||||||
|
padding-top: 10px;
|
||||||
|
border-bottom: 1px dotted #ccc;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
BIN
application/cms/public/static/cms/img/logo.png
Normal file
BIN
application/cms/public/static/cms/img/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
application/cms/public/static/cms/img/photo12@2x.jpg
Normal file
BIN
application/cms/public/static/cms/img/photo12@2x.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
BIN
application/cms/public/static/cms/img/photo3@2x.jpg
Normal file
BIN
application/cms/public/static/cms/img/photo3@2x.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 KiB |
BIN
application/cms/public/static/cms/img/preview.jpg
Normal file
BIN
application/cms/public/static/cms/img/preview.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
application/cms/public/static/cms/img/preview.png
Normal file
BIN
application/cms/public/static/cms/img/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
47
application/cms/public/static/cms/js/field.js
Normal file
47
application/cms/public/static/cms/js/field.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Document : field.js
|
||||||
|
* Author : CaiWeiMing <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
jQuery(function () {
|
||||||
|
// 字段定义列表
|
||||||
|
var $field_define_list = {
|
||||||
|
text: "varchar(128) NOT NULL",
|
||||||
|
textarea: "varchar(256) NOT NULL",
|
||||||
|
static: "varchar(128) NOT NULL",
|
||||||
|
password: "varchar(128) NOT NULL",
|
||||||
|
checkbox: "varchar(32) NOT NULL",
|
||||||
|
radio: "varchar(32) NOT NULL",
|
||||||
|
date: "int(11) UNSIGNED NOT NULL",
|
||||||
|
time: "int(11) UNSIGNED NOT NULL",
|
||||||
|
datetime: "int(11) UNSIGNED NOT NULL",
|
||||||
|
hidden: "varchar(32) NOT NULL",
|
||||||
|
switch: "varchar(16) NOT NULL",
|
||||||
|
array: "varchar(32) NOT NULL",
|
||||||
|
select: "varchar(32) NOT NULL",
|
||||||
|
linkage: "varchar(32) NOT NULL",
|
||||||
|
linkages: "varchar(32) NOT NULL",
|
||||||
|
image: "int(11) UNSIGNED NOT NULL",
|
||||||
|
images: "varchar(64) NOT NULL",
|
||||||
|
file: "int(11) UNSIGNED NOT NULL",
|
||||||
|
files: "varchar(64) NOT NULL",
|
||||||
|
ueditor: "text NOT NULL",
|
||||||
|
wangeditor: "text NOT NULL",
|
||||||
|
editormd: "text NOT NULL",
|
||||||
|
ckeditor: "text NOT NULL",
|
||||||
|
summernote: "text NOT NULL",
|
||||||
|
icon: "varchar(64) NOT NULL",
|
||||||
|
tags: "varchar(128) NOT NULL",
|
||||||
|
number: "int(11) UNSIGNED NOT NULL",
|
||||||
|
bmap: "varchar(32) NOT NULL",
|
||||||
|
colorpicker: "varchar(32) NOT NULL",
|
||||||
|
jcrop: "int(11) UNSIGNED NOT NULL",
|
||||||
|
masked: "varchar(64) NOT NULL",
|
||||||
|
range: "varchar(128) NOT NULL"
|
||||||
|
};
|
||||||
|
// 选择自动类型,自动填写字段定义
|
||||||
|
var $field_define = jQuery('input[name=define]');
|
||||||
|
jQuery('select[name=type]').change(function () {
|
||||||
|
$field_define.val($field_define_list[$(this).val()] || '');
|
||||||
|
});
|
||||||
|
});
|
320
application/cms/sql/install.sql
Normal file
320
application/cms/sql/install.sql
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
-- -----------------------------
|
||||||
|
-- 导出时间 `2016-12-13 22:26:46`
|
||||||
|
-- -----------------------------
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_advert`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_advert`;
|
||||||
|
CREATE TABLE `dp_cms_advert` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`typeid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '分类id',
|
||||||
|
`tagname` varchar(30) NOT NULL DEFAULT '' COMMENT '广告位标识',
|
||||||
|
`ad_type` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '广告类型',
|
||||||
|
`timeset` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '时间限制:0-永不过期,1-在设内时间内有效',
|
||||||
|
`start_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '开始时间',
|
||||||
|
`end_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '结束时间',
|
||||||
|
`name` varchar(60) NOT NULL DEFAULT '' COMMENT '广告位名称',
|
||||||
|
`content` text NOT NULL COMMENT '广告内容',
|
||||||
|
`expcontent` text NOT NULL COMMENT '过期显示内容',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='广告表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_advert`
|
||||||
|
-- -----------------------------
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_advert_type`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_advert_type`;
|
||||||
|
CREATE TABLE `dp_cms_advert_type` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(32) NOT NULL DEFAULT '' COMMENT '分类名称',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='广告分类表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_advert_type`
|
||||||
|
-- -----------------------------
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_column`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_column`;
|
||||||
|
CREATE TABLE `dp_cms_column` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`pid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '父级id',
|
||||||
|
`name` varchar(32) NOT NULL DEFAULT '' COMMENT '栏目名称',
|
||||||
|
`model` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '文档模型id',
|
||||||
|
`url` varchar(255) NOT NULL DEFAULT '' COMMENT '链接',
|
||||||
|
`target` varchar(16) NOT NULL DEFAULT '_self' COMMENT '链接打开方式',
|
||||||
|
`content` text NOT NULL COMMENT '内容',
|
||||||
|
`icon` varchar(64) NOT NULL DEFAULT '' COMMENT '字体图标',
|
||||||
|
`index_template` varchar(32) NOT NULL DEFAULT '' COMMENT '封面模板',
|
||||||
|
`list_template` varchar(32) NOT NULL DEFAULT '' COMMENT '列表页模板',
|
||||||
|
`detail_template` varchar(32) NOT NULL DEFAULT '' COMMENT '详情页模板',
|
||||||
|
`post_auth` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '投稿权限',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`sort` int(11) NOT NULL DEFAULT '100' COMMENT '排序',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
`hide` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '是否隐藏',
|
||||||
|
`rank_auth` int(11) NOT NULL DEFAULT '0' COMMENT '浏览权限,-1待审核,0为开放浏览,大于0则为对应的用户角色id',
|
||||||
|
`type` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '栏目属性:0-最终列表栏目,1-外部链接,2-频道封面',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='栏目表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_column`
|
||||||
|
-- -----------------------------
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_document`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_document`;
|
||||||
|
CREATE TABLE `dp_cms_document` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`cid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '栏目id',
|
||||||
|
`model` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '文档模型ID',
|
||||||
|
`title` varchar(256) NOT NULL DEFAULT '' COMMENT '标题',
|
||||||
|
`shorttitle` varchar(32) NOT NULL DEFAULT '' COMMENT '简略标题',
|
||||||
|
`uid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
|
||||||
|
`flag` set('j','p','b','s','a','f','c','h') DEFAULT NULL COMMENT '自定义属性',
|
||||||
|
`view` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '阅读量',
|
||||||
|
`comment` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '评论数',
|
||||||
|
`good` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '点赞数',
|
||||||
|
`bad` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '踩数',
|
||||||
|
`mark` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '收藏数量',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`sort` int(11) NOT NULL DEFAULT '100' COMMENT '排序',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
`trash` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '回收站',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='文档基础表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_document`
|
||||||
|
-- -----------------------------
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_field`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_field`;
|
||||||
|
CREATE TABLE `dp_cms_field` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '字段名称',
|
||||||
|
`name` varchar(32) NOT NULL,
|
||||||
|
`title` varchar(32) NOT NULL DEFAULT '' COMMENT '字段标题',
|
||||||
|
`type` varchar(32) NOT NULL DEFAULT '' COMMENT '字段类型',
|
||||||
|
`define` varchar(128) NOT NULL DEFAULT '' COMMENT '字段定义',
|
||||||
|
`value` text NULL COMMENT '默认值',
|
||||||
|
`options` text NULL COMMENT '额外选项',
|
||||||
|
`tips` varchar(256) NOT NULL DEFAULT '' COMMENT '提示说明',
|
||||||
|
`fixed` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '是否为固定字段',
|
||||||
|
`show` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '是否显示',
|
||||||
|
`model` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '所属文档模型id',
|
||||||
|
`ajax_url` varchar(256) NOT NULL DEFAULT '' COMMENT '联动下拉框ajax地址',
|
||||||
|
`next_items` varchar(256) NOT NULL DEFAULT '' COMMENT '联动下拉框的下级下拉框名,多个以逗号隔开',
|
||||||
|
`param` varchar(32) NOT NULL DEFAULT '' COMMENT '联动下拉框请求参数名',
|
||||||
|
`format` varchar(32) NOT NULL DEFAULT '' COMMENT '格式,用于格式文本',
|
||||||
|
`table` varchar(32) NOT NULL DEFAULT '' COMMENT '表名,只用于快速联动类型',
|
||||||
|
`level` tinyint(2) unsigned NOT NULL DEFAULT '2' COMMENT '联动级别,只用于快速联动类型',
|
||||||
|
`key` varchar(32) NOT NULL DEFAULT '' COMMENT '键字段,只用于快速联动类型',
|
||||||
|
`option` varchar(32) NOT NULL DEFAULT '' COMMENT '值字段,只用于快速联动类型',
|
||||||
|
`pid` varchar(32) NOT NULL DEFAULT '' COMMENT '父级id字段,只用于快速联动类型',
|
||||||
|
`ak` varchar(32) NOT NULL DEFAULT '' COMMENT '百度地图appkey',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`sort` int(11) NOT NULL DEFAULT '100' COMMENT '排序',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COMMENT='文档字段表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_field`
|
||||||
|
-- -----------------------------
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('1', 'id', 'ID', 'text', 'int(11) UNSIGNED NOT NULL', '0', '', 'ID', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480562978', '1480562978', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('2', 'cid', '栏目', 'select', 'int(11) UNSIGNED NOT NULL', '0', '', '请选择所属栏目', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480562978', '1480562978', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('3', 'uid', '用户ID', 'text', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563110', '1480563110', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('4', 'model', '模型ID', 'text', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563110', '1480563110', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('5', 'title', '标题', 'text', 'varchar(128) NOT NULL', '', '', '文档标题', '0', '1', '0', '', '', '', '', '', '0', '', '', '', '', '1480575844', '1480576134', '1', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('6', 'shorttitle', '简略标题', 'text', 'varchar(32) NOT NULL', '', '', '简略标题', '0', '1', '0', '', '', '', '', '', '0', '', '', '', '', '1480575844', '1480576134', '1', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('7', 'flag', '自定义属性', 'checkbox', 'set(\'j\',\'p\',\'b\',\'s\',\'a\',\'f\',\'h\',\'c\') NULL DEFAULT NULL', '', 'j:跳转\r\np:图片\r\nb:加粗\r\ns:滚动\r\na:特荐\r\nf:幻灯\r\nh:头条\r\nc:推荐', '自定义属性', '0', '1', '0', '', '', '', '', '', '0', '', '', '', '', '1480671258', '1480671258', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('8', 'view', '阅读量', 'text', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '1', '0', '', '', '', '', '', '0', '', '', '', '', '1480563149', '1480563149', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('9', 'comment', '评论数', 'text', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563189', '1480563189', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('10', 'good', '点赞数', 'text', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563279', '1480563279', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('11', 'bad', '踩数', 'text', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563330', '1480563330', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('12', 'mark', '收藏数量', 'text', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563372', '1480563372', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('13', 'create_time', '创建时间', 'datetime', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563406', '1480563406', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('14', 'update_time', '更新时间', 'datetime', 'int(11) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563432', '1480563432', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('15', 'sort', '排序', 'text', 'int(11) NOT NULL', '100', '', '', '0', '1', '0', '', '', '', '', '', '0', '', '', '', '', '1480563510', '1480563510', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('16', 'status', '状态', 'radio', 'tinyint(2) UNSIGNED NOT NULL', '1', '0:禁用\r\n1:启用', '', '0', '1', '0', '', '', '', '', '', '0', '', '', '', '', '1480563576', '1480563576', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_field` VALUES ('17', 'trash', '回收站', 'text', 'tinyint(2) UNSIGNED NOT NULL', '0', '', '', '0', '0', '0', '', '', '', '', '', '0', '', '', '', '', '1480563576', '1480563576', '100', '1');
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_link`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_link`;
|
||||||
|
CREATE TABLE `dp_cms_link` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`type` tinyint(2) unsigned NOT NULL DEFAULT '1' COMMENT '类型:1-文字链接,2-图片链接',
|
||||||
|
`title` varchar(128) NOT NULL DEFAULT '' COMMENT '链接标题',
|
||||||
|
`url` varchar(255) NOT NULL DEFAULT '' COMMENT '链接地址',
|
||||||
|
`logo` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '链接LOGO',
|
||||||
|
`contact` varchar(255) NOT NULL DEFAULT '' COMMENT '联系方式',
|
||||||
|
`sort` int(11) NOT NULL DEFAULT '100',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='有钱链接表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_link`
|
||||||
|
-- -----------------------------
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_menu`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_menu`;
|
||||||
|
CREATE TABLE `dp_cms_menu` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`nid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '导航id',
|
||||||
|
`pid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '父级id',
|
||||||
|
`column` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '栏目id',
|
||||||
|
`page` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '单页id',
|
||||||
|
`type` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '类型:0-栏目链接,1-单页链接,2-自定义链接',
|
||||||
|
`title` varchar(128) NOT NULL DEFAULT '' COMMENT '菜单标题',
|
||||||
|
`url` varchar(255) NOT NULL DEFAULT '' COMMENT '链接',
|
||||||
|
`css` varchar(64) NOT NULL DEFAULT '' COMMENT 'css类',
|
||||||
|
`rel` varchar(64) NOT NULL DEFAULT '' COMMENT '链接关系网',
|
||||||
|
`target` varchar(16) NOT NULL DEFAULT '' COMMENT '打开方式',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`sort` int(11) NOT NULL DEFAULT '100' COMMENT '排序',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='菜单表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_menu`
|
||||||
|
-- -----------------------------
|
||||||
|
INSERT INTO `dp_cms_menu` VALUES ('1', '1', '0', '0', '0', '2', '首页', 'cms/index/index', '', '', '_self', '1492345605', '1492345605', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_menu` VALUES ('2', '2', '0', '0', '0', '2', '关于我们', 'http://www.dolphinphp.com', '', '', '_self', '1492346763', '1492346763', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_menu` VALUES ('3', '3', '0', '0', '0', '2', '开发文档', 'http://www.kancloud.cn/ming5112/dolphinphp', '', '', '_self', '1492346812', '1492346812', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_menu` VALUES ('4', '3', '0', '0', '0', '2', '开发者社区', 'http://bbs.dolphinphp.com/', '', '', '_self', '1492346832', '1492346832', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_menu` VALUES ('5', '1', '0', '0', '0', '2', '二级菜单', 'http://www.dolphinphp.com', '', '', '_self', '1492347372', '1492347510', '100', '1');
|
||||||
|
INSERT INTO `dp_cms_menu` VALUES ('6', '1', '5', '0', '0', '2', '子菜单', 'http://www.dolphinphp.com', '', '', '_self', '1492347388', '1492347520', '100', '1');
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_model`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_model`;
|
||||||
|
CREATE TABLE `dp_cms_model` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(32) NOT NULL DEFAULT '' COMMENT '模型名称',
|
||||||
|
`title` varchar(32) NOT NULL DEFAULT '' COMMENT '模型标题',
|
||||||
|
`table` varchar(64) NOT NULL DEFAULT '' COMMENT '附加表名称',
|
||||||
|
`type` tinyint(2) NOT NULL DEFAULT '1' COMMENT '模型类别:0-系统模型,1-普通模型,2-独立模型',
|
||||||
|
`icon` varchar(64) NOT NULL,
|
||||||
|
`sort` int(11) NOT NULL DEFAULT '100' COMMENT '排序',
|
||||||
|
`system` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '是否系统模型',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='内容模型表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_nav`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_nav`;
|
||||||
|
CREATE TABLE `dp_cms_nav` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`tag` varchar(32) NOT NULL DEFAULT '' COMMENT '导航标识',
|
||||||
|
`title` varchar(32) NOT NULL DEFAULT '' COMMENT '菜单标题',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='导航表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_nav`
|
||||||
|
-- -----------------------------
|
||||||
|
INSERT INTO `dp_cms_nav` VALUES ('1', 'main_nav', '顶部导航', '1492345083', '1492345083', '1');
|
||||||
|
INSERT INTO `dp_cms_nav` VALUES ('2', 'about_nav', '底部关于', '1492346685', '1492346685', '1');
|
||||||
|
INSERT INTO `dp_cms_nav` VALUES ('3', 'support_nav', '服务与支持', '1492346715', '1492346715', '1');
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_page`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_page`;
|
||||||
|
CREATE TABLE `dp_cms_page` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`title` varchar(64) NOT NULL DEFAULT '' COMMENT '单页标题',
|
||||||
|
`content` mediumtext NOT NULL COMMENT '单页内容',
|
||||||
|
`keywords` varchar(32) NOT NULL DEFAULT '' COMMENT '关键词',
|
||||||
|
`description` varchar(250) NOT NULL DEFAULT '' COMMENT '页面描述',
|
||||||
|
`template` varchar(32) NOT NULL DEFAULT '' COMMENT '模板文件',
|
||||||
|
`cover` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '单页封面',
|
||||||
|
`view` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '阅读量',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='单页表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_page`
|
||||||
|
-- -----------------------------
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_slider`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_slider`;
|
||||||
|
CREATE TABLE `dp_cms_slider` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`title` varchar(32) NOT NULL DEFAULT '' COMMENT '标题',
|
||||||
|
`cover` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '封面id',
|
||||||
|
`url` varchar(255) NOT NULL DEFAULT '' COMMENT '链接地址',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
`sort` int(11) unsigned NOT NULL DEFAULT '100' COMMENT '排序',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='滚动图片表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_slider`
|
||||||
|
-- -----------------------------
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表结构 `dp_cms_support`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_support`;
|
||||||
|
CREATE TABLE `dp_cms_support` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(128) NOT NULL DEFAULT '' COMMENT '客服名称',
|
||||||
|
`qq` varchar(16) NOT NULL DEFAULT '' COMMENT 'QQ',
|
||||||
|
`msn` varchar(100) NOT NULL DEFAULT '' COMMENT 'msn',
|
||||||
|
`taobao` varchar(100) NOT NULL DEFAULT '' COMMENT 'taobao',
|
||||||
|
`alibaba` varchar(100) NOT NULL DEFAULT '' COMMENT 'alibaba',
|
||||||
|
`skype` varchar(100) NOT NULL DEFAULT '' COMMENT 'skype',
|
||||||
|
`status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
|
||||||
|
`sort` int(11) unsigned NOT NULL DEFAULT '100' COMMENT '排序',
|
||||||
|
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='客服表';
|
||||||
|
|
||||||
|
-- -----------------------------
|
||||||
|
-- 表数据 `dp_cms_support`
|
||||||
|
-- -----------------------------
|
15
application/cms/sql/uninstall.sql
Normal file
15
application/cms/sql/uninstall.sql
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
-- -----------------------------
|
||||||
|
-- 导出时间 `2016-12-13 22:26:46`
|
||||||
|
-- -----------------------------
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_advert`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_advert_type`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_column`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_document`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_field`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_link`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_menu`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_model`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_nav`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_page`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_slider`;
|
||||||
|
DROP TABLE IF EXISTS `dp_cms_support`;
|
34
application/cms/uninstall.php
Normal file
34
application/cms/uninstall.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
use think\Db;
|
||||||
|
use think\Exception;
|
||||||
|
// cms模块卸载文件
|
||||||
|
|
||||||
|
// 是否清除数据
|
||||||
|
$clear = $this->request->get('clear');
|
||||||
|
|
||||||
|
if ($clear == 1) {
|
||||||
|
// 内容模型的表名列表
|
||||||
|
$table_list = Db::name('cms_model')->column('table');
|
||||||
|
|
||||||
|
if ($table_list) {
|
||||||
|
foreach ($table_list as $table) {
|
||||||
|
// 删除内容模型表
|
||||||
|
$sql = 'DROP TABLE IF EXISTS `'.$table.'`;';
|
||||||
|
try {
|
||||||
|
Db::execute($sql);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw new Exception('删除表:'.$table.' 失败!', 1001);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
application/cms/validate/Action.php
Normal file
35
application/cms/validate/Action.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\cms\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行为验证器
|
||||||
|
* @package app\cms\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Action extends Validate
|
||||||
|
{
|
||||||
|
//定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'module|所属模块' => 'require',
|
||||||
|
'name|行为标识' => 'require|regex:^[a-zA-Z]\w{0,39}$|unique:admin_action',
|
||||||
|
'title|行为名称' => 'require|length:1,80',
|
||||||
|
'remark|行为描述' => 'require|length:1,128'
|
||||||
|
];
|
||||||
|
|
||||||
|
//定义验证提示
|
||||||
|
protected $message = [
|
||||||
|
'name.regex' => '行为标识由字母和下划线组成',
|
||||||
|
];
|
||||||
|
}
|
55
application/cms/validate/Advert.php
Normal file
55
application/cms/validate/Advert.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\cms\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告验证器
|
||||||
|
* @package app\cms\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Advert extends Validate
|
||||||
|
{
|
||||||
|
// 定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'typeid|广告分类' => 'require',
|
||||||
|
'tagname|广告位标识' => 'require|regex:^[a-z]+[a-z0-9_]{0,20}$|unique:cms_advert',
|
||||||
|
'name|广告位名称' => 'require|unique:cms_advert',
|
||||||
|
'start_time' => 'requireIf:timeset,1',
|
||||||
|
'end_time' => 'requireIf:timeset,1',
|
||||||
|
'title' => 'requireIf:ad_type,1',
|
||||||
|
'code' => 'requireIf:ad_type,0',
|
||||||
|
'size' => 'integer',
|
||||||
|
'width' => 'integer',
|
||||||
|
'height' => 'integer',
|
||||||
|
'src' => 'requireIf:ad_type,2',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 定义验证提示
|
||||||
|
protected $message = [
|
||||||
|
'tagname.regex' => '广告位标识由小写字母、数字或下划线组成,不能以数字开头',
|
||||||
|
'code' => '代码不能为空',
|
||||||
|
'src' => '请上传图片',
|
||||||
|
'title' => '文字内容不能为空',
|
||||||
|
'start_time' => '开始时间不能为空',
|
||||||
|
'end_time' => '结束时间不能为空',
|
||||||
|
'size' => '文字大小只能填写数字',
|
||||||
|
'width' => '宽度只能填写数字',
|
||||||
|
'height' => '高度只能填写数字',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 定义验证场景
|
||||||
|
protected $scene = [
|
||||||
|
'name' => ['name']
|
||||||
|
];
|
||||||
|
}
|
32
application/cms/validate/AdvertType.php
Normal file
32
application/cms/validate/AdvertType.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\cms\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告分类验证器
|
||||||
|
* @package app\cms\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class AdvertType extends Validate
|
||||||
|
{
|
||||||
|
// 定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'name|分类名称' => 'require|length:1,30|unique:cms_advert_type'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 定义验证场景
|
||||||
|
protected $scene = [
|
||||||
|
'name' => ['name']
|
||||||
|
];
|
||||||
|
}
|
29
application/cms/validate/Column.php
Normal file
29
application/cms/validate/Column.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\cms\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 栏目验证器
|
||||||
|
* @package app\cms\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Column extends Validate
|
||||||
|
{
|
||||||
|
// 定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'pid|所属栏目' => 'require',
|
||||||
|
'name|栏目名称' => 'require|unique:cms_column,name^pid',
|
||||||
|
'model|内容模型' => 'require',
|
||||||
|
];
|
||||||
|
}
|
36
application/cms/validate/Field.php
Normal file
36
application/cms/validate/Field.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\cms\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档字段验证器
|
||||||
|
* @package app\cms\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Field extends Validate
|
||||||
|
{
|
||||||
|
//定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'name|字段名称' => 'require|regex:^[a-z]\w{0,39}$|unique:cms_field,name^model',
|
||||||
|
'title|字段标题' => 'require|length:1,30',
|
||||||
|
'type|字段类型' => 'require|length:1,30',
|
||||||
|
'define|字段定义' => 'require|length:1,100',
|
||||||
|
'tips|字段说明' => 'length:1,200',
|
||||||
|
];
|
||||||
|
|
||||||
|
//定义验证提示
|
||||||
|
protected $message = [
|
||||||
|
'name.regex' => '字段名称由小写字母和下划线组成',
|
||||||
|
];
|
||||||
|
}
|
40
application/cms/validate/Link.php
Normal file
40
application/cms/validate/Link.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 海豚PHP框架 [ DolphinPHP ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 官方网站: http://dolphinphp.com
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\cms\validate;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 友情链接验证器
|
||||||
|
* @package app\cms\validate
|
||||||
|
* @author 蔡伟明 <314013107@qq.com>
|
||||||
|
*/
|
||||||
|
class Link extends Validate
|
||||||
|
{
|
||||||
|
// 定义验证规则
|
||||||
|
protected $rule = [
|
||||||
|
'title|链接标题' => 'require|length:1,30',
|
||||||
|
'url|链接地址' => 'require|url',
|
||||||
|
'logo|链接LOGO' => 'requireIf:type,2',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 定义验证提示
|
||||||
|
protected $message = [
|
||||||
|
'logo.requireIf' => '请上传链接LOGO',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 定义验证场景
|
||||||
|
protected $scene = [
|
||||||
|
'title' => ['title'],
|
||||||
|
'url' => ['url' => 'require'],
|
||||||
|
];
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user