diff --git a/README.md b/README.md index 224b07b0..cae88179 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ [![License](https://img.shields.io/badge/license-GPL_V3.0-yellowgreen.svg)](https://github.com/wisp-x/lsky-pro/blob/master/LICENSE) [![PHP](https://img.shields.io/badge/PHP->=5.6-orange.svg)](http://php.net) [![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/wisp-x/lsky-pro.svg)](https://github.com/wisp-x/lsky-pro) -[![Join the chat at https://gitter.im/wisp-x/lsky-pro](https://badges.gitter.im/wisp-x/lsky-pro.svg)](https://gitter.im/wisp-x/lsky-pro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge&style=flat-square) +[![Join the chat at https://gitter.im/wisp-x/lsky-pro](https://badges.gitter.im/wisp-x/lsky-pro.svg)](https://gitter.im/wisp-x/lsky-pro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) > master分支为最新版,其他版本请点击[这里](https://github.com/wisp-x/lsky-pro/releases) diff --git a/application/common/model/Group.php b/application/common/model/Group.php new file mode 100644 index 00000000..ac6ba1a5 --- /dev/null +++ b/application/common/model/Group.php @@ -0,0 +1,24 @@ +where('default', 1)->setField('default', 0); + } + return $default ? 1 : 0; + } +} diff --git a/application/common/model/Users.php b/application/common/model/Users.php index ab616464..ae18623a 100644 --- a/application/common/model/Users.php +++ b/application/common/model/Users.php @@ -80,4 +80,9 @@ class Users extends Model { return $this->hasMany('Folders', 'user_id', 'id'); } + + public function group() + { + return $this->hasOne('Group', 'id', 'group_id'); + } } diff --git a/application/common/validate/Group.php b/application/common/validate/Group.php new file mode 100644 index 00000000..0712711f --- /dev/null +++ b/application/common/validate/Group.php @@ -0,0 +1,24 @@ + 'require|max:30|chsAlphaNum' + ]; + + protected $message = [ + 'name.require' => '角色组名称不能为空', + 'name.max' => '角色组名称长度最大30个字符', + 'name.chsAlphaNum' => '角色组名称只能是汉字、字母和数字' + ]; +} diff --git a/application/index/controller/Base.php b/application/index/controller/Base.php index c273499c..e2a8968f 100644 --- a/application/index/controller/Base.php +++ b/application/index/controller/Base.php @@ -8,6 +8,7 @@ namespace app\index\controller; +use app\common\model\Group; use app\common\model\Users; use PHPMailer\PHPMailer\PHPMailer; use think\Controller; @@ -26,6 +27,8 @@ class Base extends Controller protected $configs = null; + protected $group = null; + /** * 当前储存策略配置 * @@ -55,13 +58,22 @@ class Base extends Controller } // 检测数据库结构更新 - if ($this->user && $this->user->is_admin) { + if ($this->user && $this->user->is_admin && !\config('app.app_debug')) { if (file_exists(Env::get('root_path') . 'update.sql')) { $this->redirect(url('/install/update')); } } - $this->currentStrategyConfig = $this->getStrategyConfig(strtolower($this->config['storage_strategy'])); + // 角色组 + if ($this->user) { + $this->group = $this->user->group; + } + if (!$this->group) { + // 默认角色组 + $this->group = Group::where('default', 1)->find(); + } + + $this->currentStrategyConfig = $this->getStrategyConfig(strtolower($this->group->strategy)); $this->assign([ 'config' => $this->config, @@ -96,7 +108,7 @@ class Base extends Controller */ protected function getStrategyInstance($strategy = null) { - $currentStrategy = $strategy ? $strategy : strtolower($this->config['storage_strategy']); + $currentStrategy = $strategy ? $strategy : strtolower($this->group->strategy); // 驱动 $driver = Config::get('strategy.' . $currentStrategy . '.class'); // 获取该储存策略配置 diff --git a/application/index/controller/Index.php b/application/index/controller/Index.php index 005cc557..eafb759b 100644 --- a/application/index/controller/Index.php +++ b/application/index/controller/Index.php @@ -8,10 +8,13 @@ namespace app\index\controller; +use app\common\model\Images; + class Index extends Base { public function index() { + $this->assign('images_count', Images::cache(120)->count()); return $this->fetch(); } diff --git a/application/index/controller/Install.php b/application/index/controller/Install.php index 1a5c942d..ae27de6c 100644 --- a/application/index/controller/Install.php +++ b/application/index/controller/Install.php @@ -217,10 +217,12 @@ EOT; // 新建表字段 $tableFields = [ 'lsky_images' => [ - 'folder_id' => "ALTER TABLE `lsky_images` ADD `folder_id` INT NOT NULL DEFAULT '0' COMMENT '文件夹ID' AFTER `user_id`;" + 'folder_id' => "ALTER TABLE `lsky_images` ADD `folder_id` INT NOT NULL DEFAULT '0' COMMENT '文件夹ID' AFTER `user_id`;", + 'suspicious' => "ALTER TABLE `lsky_images` ADD `suspicious` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '可疑图片' AFTER `ip`;", ], 'lsky_users' => [ - 'default_folder' => "ALTER TABLE `lsky_users` ADD `default_folder` VARCHAR(32) DEFAULT NULL COMMENT '默认上传文件夹' AFTER `quota`;" + 'default_folder' => "ALTER TABLE `lsky_users` ADD `default_folder` VARCHAR(32) DEFAULT NULL COMMENT '默认上传文件夹' AFTER `quota`;", + 'group_id' => "ALTER TABLE `lsky_users` ADD `group_id` int(11) NOT NULL DEFAULT 0 COMMENT '角色组ID' AFTER `id`;" ], ]; @@ -245,7 +247,7 @@ EOT; foreach (explode(';', $file) as $value) { if ($value && !ctype_space($value)) { if (!$mysqli->query($value . ';')) { - throw new Exception('数据导入失败,错误信息:' . $mysqli->error . ',sql语句:' . $value); + throw new Exception('

数据导入失败!

错误信息:
' . $mysqli->error . '

sql语句:
' . $value . '

'); } } } diff --git a/application/index/controller/Upload.php b/application/index/controller/Upload.php index f576a9ca..557a3f7c 100644 --- a/application/index/controller/Upload.php +++ b/application/index/controller/Upload.php @@ -91,6 +91,7 @@ class Upload extends Base $url = make_url($domain, $pathname); // 图片鉴黄 + $suspicious = 0; if ($this->config['open_audit']) { $client = new Client(); $response = $client->get("https://www.moderatecontent.com/api/v2?key={$this->config['audit_key']}&url={$url}"); @@ -98,8 +99,9 @@ class Upload extends Base $result = json_decode($response->getBody()->getContents()); if (0 == $result->error_code) { if ($result->rating_index >= $this->config['audit_index']) { - $strategy->delete($pathname); - throw new Exception('图片[' . $image->getInfo('name') . ']涉嫌违规,禁止上传!'); + /*$strategy->delete($pathname); + throw new Exception('图片[' . $image->getInfo('name') . ']涉嫌违规,禁止上传!');*/ + $suspicious = 1; } } else { $strategy->delete($pathname); @@ -117,7 +119,8 @@ class Upload extends Base 'size' => $size, 'mime' => $mime, 'sha1' => $sha1, - 'md5' => $md5 + 'md5' => $md5, + 'suspicious' => $suspicious ]; // 默认上传文件夹,暂只支持一级 diff --git a/application/index/controller/admin/Group.php b/application/index/controller/admin/Group.php new file mode 100644 index 00000000..ae7caf2b --- /dev/null +++ b/application/index/controller/admin/Group.php @@ -0,0 +1,150 @@ +strategyList = Config::pull('strategy'); + } + + public function index() + { + $groups = GroupModel::select()->each(function ($item) { + $item->strategy_str = isset($this->strategyList[$item->strategy]) ? $this->strategyList[$item->strategy]['name'] : '未知'; + return $item; + }); + $this->assign([ + 'groups' => $groups, + 'strategy_list' => $this->strategyList + ]); + + return $this->fetch(); + } + + public function add() + { + if ($this->request->isPost()) { + try { + $data = $this->request->post(); + $validate = $this->validate($data, 'Group'); + if (true !== $validate) { + throw new Exception($validate); + } + if (!GroupModel::create($data)) { + throw new Exception('添加失败'); + } + } catch (Exception $e) { + return $this->error($e->getMessage()); + } + + return $this->success('添加成功'); + } + } + + public function edit() + { + if ($this->request->isPost()) { + try { + $data = $this->request->post(); + $validate = $this->validate($data, 'Group'); + if (true !== $validate) { + throw new Exception($validate); + } + if (!GroupModel::update($data)) { + throw new Exception('编辑失败'); + } + } catch (Exception $e) { + return $this->error($e->getMessage()); + } + return $this->success('编辑成功'); + } + } + + public function del() + { + if ($this->request->isPost()) { + Db::startTrans(); + try { + $id = $this->request->post('id'); + $group = GroupModel::find($id); + // 至少保留一个默认分组 + $defaultId = GroupModel::where('default', 1)->where('id', 'neq', $id)->value('id'); + if (!$defaultId) { + throw new Exception('至少保留一个默认分组'); + } + // 转移该组下的用户到默认分组 + if (!\app\common\model\Users::where('group_id', $group->id)->setField('group_id', $defaultId)) { + throw new Exception('删除失败'); + } + $group->delete(); + Db::commit(); + } catch (Exception $e) { + Db::rollback(); + return $this->error($e->getMessage()); + } + return $this->success('删除成功'); + } + } + + public function getGroup() + { + if ($this->request->isPost()) { + $id = $this->request->post('id'); + return $this->success('success', null, GroupModel::find($id)); + } + } + + public function setDefault() + { + if ($this->request->isPost()) { + $id = $this->request->post('id'); + $value = $this->request->post('value'); + if (1 != $value) { + if (!GroupModel::where('default', 1)->where('id', 'neq', $id)->count()) { + return $this->error('至少保留一个默认分组'); + } + } + if (!GroupModel::update([ + 'id' => $id, + 'default' => $value + ])) { + return $this->error('设置失败'); + } + return $this->success('设置成功'); + } + } + + public function setStrategy() + { + if ($this->request->isPost()) { + $id = $this->request->post('id'); + $strategy = $this->request->post('strategy'); + if (!array_key_exists($strategy, $this->strategyList)) { + return $this->error('储存策略不存在'); + } + if (!GroupModel::update([ + 'id' => $id, + 'strategy' => $strategy + ])) { + return $this->error('设置失败'); + } + return $this->success('设置成功'); + } + } +} diff --git a/application/index/controller/admin/Images.php b/application/index/controller/admin/Images.php index 05924148..6365051a 100644 --- a/application/index/controller/admin/Images.php +++ b/application/index/controller/admin/Images.php @@ -30,14 +30,20 @@ class Images extends Base { parent::initialize(); $this->strategyList = Config::pull('strategy'); - $this->assign('strategyList', $this->strategyList); + $this->assign('strategy_list', $this->strategyList); } - public function index($strategy = '', $keyword = '', $limit = 15) + public function index($where = '', $keyword = '', $limit = 15) { + $where = json_decode($where, true); + if (null == $where) { + $where = [ + 'suspicious' => 0 + ]; + } $model = new ImagesModel(); - if (!empty($strategy)) { - $model = $model->where('strategy', $strategy); + foreach ($where as $field => $value) { + $model = $model->where($field, $value); } if (!empty($keyword)) { $model = $model->where('pathname|sha1|md5', 'like', "%{$keyword}%"); @@ -47,7 +53,8 @@ class Images extends Base 'keyword' => $keyword ] ])->each(function ($item) { - $item->username = Users::where('id', $item->user_id)->value('username'); + $username = Users::where('id', $item->user_id)->value('username'); + $item->username = $username ? $username : '访客'; $item->strategyStr = isset($this->strategyList[$item->strategy]) ? $this->strategyList[$item->strategy]['name'] : '未知'; return $item; }); @@ -55,8 +62,10 @@ class Images extends Base 'images' => $images, 'keyword' => $keyword, 'strategyList' => $this->strategyList, - 'strategy' => $strategy + 'strategy' => isset($where['strategy']) ? $where['strategy'] : '', + 'suspicious' => isset($where['suspicious']) ? $where['suspicious'] : 0 ]); + return $this->fetch(); } @@ -130,7 +139,7 @@ class Images extends Base } catch (Exception $e) { return $this->error('获取失败'); } catch (RequestException $e) { - return $this->error('淘宝接口异常'); + return $this->error('淘宝接口发生异常,状态码:' . $response->getStatusCode()); } return $this->success('获取成功', null, $data); } diff --git a/application/index/view/admin/group/index.html b/application/index/view/admin/group/index.html new file mode 100644 index 00000000..bbe8520c --- /dev/null +++ b/application/index/view/admin/group/index.html @@ -0,0 +1,201 @@ +{extend name="common:base" /} + +{block name="title"}角色组 - {$config.site_name}{/block} + +{block name="main"} +
+
+
+
+
+

不同的角色组下的用户,上传图片将使用不同的储存策略。
至少有一个默认角色组,新注册用户和访客将会使用默认的角色组。
角色组删除后,该组下面的用户将重置默认角色组。

+
+
+
+ +
+ + + + + + + + + + + {foreach $groups as $value} + + + + + + + {/foreach} + +
使用策略名称注册默认操作
+ + {$value.name} + + +
+ + +
+
+
+
+
+
+
+
添加角色组
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
+
添加角色组
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+
+
+
+{/block} + +{block name="js"} + +{/block} diff --git a/application/index/view/admin/images/index.html b/application/index/view/admin/images/index.html index 0c57b8d8..2440d6d8 100644 --- a/application/index/view/admin/images/index.html +++ b/application/index/view/admin/images/index.html @@ -11,16 +11,17 @@
- 系统共有 {$images->total()} 张图片 + 共有 {$images->total()} 张图片
- {foreach $strategyList as $key => $value} - + {/foreach} + @@ -98,6 +99,9 @@ }, {confirmText: '确定', cancelText: '取消'}); } }; + $('.mdui-select.where').on('close.mdui.select', function () { + $('#search-form').submit(); + }); $('.mdui-select.operation').on('close.mdui.select', function () { if ($(this).val() !== '') { var selected = $('tr.mdui-table-row-selected'); diff --git a/application/index/view/admin/strategy/index.html b/application/index/view/admin/strategy/index.html index 70b488f5..f33a6535 100644 --- a/application/index/view/admin/strategy/index.html +++ b/application/index/view/admin/strategy/index.html @@ -6,9 +6,10 @@
-
- - +
+
+

储存策略,可配置多个,使用不同的角色组来控制用户图片储存策略。

+
{foreach $strategy as $key => $value} @@ -44,19 +45,6 @@ -{/block} \ No newline at end of file +{/block} diff --git a/application/index/view/admin/system/index.html b/application/index/view/admin/system/index.html index bfbda560..778c9dd0 100644 --- a/application/index/view/admin/system/index.html +++ b/application/index/view/admin/system/index.html @@ -6,6 +6,11 @@
+
+
+

系统配置,统计代码中注意要使用<script></script>标签,不设置可为空。

+
+
基础配置 上传配置 @@ -26,7 +31,7 @@ {/case} {case textarea} - + {/case} {case bool}