diff --git a/README.md b/README.md
index e5cd7c5..89bbd7d 100644
--- a/README.md
+++ b/README.md
@@ -4,10 +4,10 @@
## 原程序(已停止维护)
-项目:兰空图床
-作者:WispX
-作者博客:https://www.wispx.cn/
-源项目:https://gitee.com/wispx/lsky
+ - 项目:兰空图床
+ - 作者:WispX
+ - 作者博客:https://www.wispx.cn/
+ - 源项目:https://gitee.com/wispx/lsky
## 新特性
diff --git a/app/.htaccess b/app/.htaccess
new file mode 100644
index 0000000..3418e55
--- /dev/null
+++ b/app/.htaccess
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/app/admin/config.php b/app/admin/config.php
new file mode 100644
index 0000000..a279f8d
--- /dev/null
+++ b/app/admin/config.php
@@ -0,0 +1,10 @@
+ 'auth', 'domain' => $_SERVER['HTTP_HOST']]), true);
+ //if(!$auth['code']) die('程序未授权,请联系QQ:1591788658 授权!');
+ if(empty(session('admin')) || empty(cookie('admin'))) return $this->redirect('login/');
+ $this->admin = Db::name('user')->where('username', session('admin'))->find();
+ if(count($this->admin) > 0) {
+ $this->web = Config::get('web');
+ $this->conf = getSystemConf();
+ $this->conf['file_path'] = Config::get('file_path');
+ $this->conf['theme_path'] = Config::get('theme_path');
+ $this->scheme = getSchemeList();
+ $this->assign('admin', $this->admin);
+ $this->assign('web', $this->web);
+ $this->assign('conf', $this->conf);
+ } else {
+ session('admin', null);
+ cookie('admin', null);
+ return $this->redirect('login/');
+ }
+ }
+
+ public function index()
+ {
+ return $this->fetch();
+ }
+
+ /**
+ * 自定义加密方式
+ * @param $str
+ * @return string
+ */
+ protected function md6($str)
+ {
+ return md5("LK{$str}");
+ }
+
+ /**
+ * 直接返回json
+ * @param int $code 状态码
+ * @param string $msg 状态信息
+ * @param string $data 返回数据(可选)
+ * @return \think\response\Json
+ */
+ protected function json($code, $msg, $data = '', $url = '', $count = '')
+ {
+ $result = ['code' => $code, 'msg' => $msg];
+ if(!empty($data)) $result['data'] = $data;
+ if(!empty($url)) $result['url'] = $url;
+ if(!empty($count)) $result['count'] = $count;
+ return json($result);
+ }
+
+}
\ No newline at end of file
diff --git a/app/admin/controller/Console.php b/app/admin/controller/Console.php
new file mode 100644
index 0000000..952b57b
--- /dev/null
+++ b/app/admin/controller/Console.php
@@ -0,0 +1,34 @@
+count();
+ // 今日新增图片
+ $data['add_img_num'] = $file_db->where(['upload_time' => ['gt', strtotime(date('Y-m-d', time()))]])->count();
+ // 用户总数
+ $data['user_num'] = $user_db->count();
+ // 今日新增用户
+ $data['add_user_num'] = $user_db->where(['reg_time' => ['gt', strtotime(date('Y-m-d', time()))]])->count();
+ // 总占用内存
+ $data['occupy'] = round($file_db->sum('size') / 1024 / 1024, 2);
+ // 上传文件限制
+ $data['upload_max_filesize'] = ini_get('upload_max_filesize');
+ // 执行时间限制
+ $data['max_execution_time'] = ini_get('max_execution_time');
+ // 剩余空间
+ $data['disk_free_space'] = round((disk_free_space(".") / (1024 * 1024)), 2);
+ // 获取公告
+ $data['notice'] = json_decode(curl('https://service.lskys.cc/server.php', ['action' => 'getNoticeAll']), true);
+ $this->assign('data', $data);
+ return $this->fetch();
+ }
+}
diff --git a/app/admin/controller/Index.php b/app/admin/controller/Index.php
new file mode 100644
index 0000000..f4b0848
--- /dev/null
+++ b/app/admin/controller/Index.php
@@ -0,0 +1,18 @@
+fetch();
+ }
+
+ public function logout()
+ {
+ session('admin', null);
+ cookie('admin', null);
+ return $this->redirect('/');
+ }
+}
diff --git a/app/admin/controller/Login.php b/app/admin/controller/Login.php
new file mode 100644
index 0000000..07720c4
--- /dev/null
+++ b/app/admin/controller/Login.php
@@ -0,0 +1,43 @@
+isAjax()) {
+ $input = trimArray(Request::instance()->post());
+ $user_db = Db::name('user');
+ if(filter_var($input['user'], FILTER_VALIDATE_EMAIL)) {
+ // 验证邮箱
+ $where = ['email' => $input['user'], 'id' => 1];
+ $is_user = $user_db->where($where)->count() > 0 ? true : false;
+ $user = '邮箱';
+ } else {
+ // 验证用户名
+ $where = ['username' => $input['user'], 'id' => 1];
+ $is_user = $user_db->where($where)->count() > 0 ? true : false;
+ $user = '用户名';
+ }
+ if(!$is_user) return parent::json(0, "{$user}不存在!");
+ $where['password'] = $this->md6($input['password']);
+ $user = $user_db->where($where)->find();
+ if($user) {
+ session('admin', $user['username']);
+ cookie('admin', $user['username']);
+ return parent::json(1, '登录成功');
+ }
+ return parent::json(0, "{$user}或密码错误!");
+ }
+ return $this->fetch();
+ }
+}
diff --git a/app/admin/controller/Picture.php b/app/admin/controller/Picture.php
new file mode 100644
index 0000000..387e0aa
--- /dev/null
+++ b/app/admin/controller/Picture.php
@@ -0,0 +1,158 @@
+fetch();
+ }
+
+ public function getFileList($page = 0, $limit = 0, array $key = [])
+ {
+ $map['id'] = ['gt', 0];
+ if(count($key) > 0) $map = $key;
+ $file_db = Db::name('file');
+ $file_list = $file_db->where($map)->order('upload_time desc')->page($page, $limit)->select();
+ // 上传方案
+ $scheme = getSchemeList();
+ foreach ($file_list as &$val) {
+ $val['upload_time'] = formatTime($val['upload_time']);
+ $val['size'] = round(($val['size'] / 1024 / 1024), 2) . 'Mb';
+ $val['user_id'] = $this->getUserName($val['user_id']);
+ switch ($val['scheme_id']) {
+ case 1:
+ $url = "{$this->web['domain']}/pic/{$val['path']}"; break;
+ case 2:
+ $url = "{$scheme['qiniu']['domain']}/{$val['path']}"; break;
+ case 3:
+ $url = "{$scheme['upyun']['domain']}/{$val['path']}"; break;
+ // TODO case 4
+ }
+ $val['name'] = "{$val['name']}";
+ }
+ return parent::json(0, '', $file_list, '', $file_db->count());
+ }
+
+ /**
+ * 删除文件及记录
+ * @param $id
+ * @return \think\response\Json
+ */
+ public function del($id)
+ {
+ if(Request::instance()->isAjax()) {
+ Db::startTrans();
+ try {
+ $file_db = Db::name('file');
+ $map = ['id' => $id];
+ $file_info = $file_db->where($map)->find();
+ switch ((int)$file_info['scheme_id']) {
+ case 1: // 删除本地文件
+ // 删除文件记录
+ if($file_db->where($map)->delete()) {
+ // 删除文件
+ @unlink("{$this->conf['file_path']}/{$file_info['path']}");
+ }
+ break;
+ case 2: // 删除七牛云文件
+ $auth = new Auth($this->scheme['qiniu']['access_key'], $this->scheme['qiniu']['secret_key']);
+ $config = new \Qiniu\Config();
+ $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
+ $bucketManager->delete($this->scheme['qiniu']['bucket_name'], $file_info['path']);
+ $file_db->where($map)->delete();
+ break;
+ case 3: // 删除又拍云文件
+ if($file_db->where($map)->delete()) {
+ // 创建实例
+ $bucketConfig = new \Upyun\Config($this->scheme['upyun']['bucket_name'], $this->scheme['upyun']['access_key'], $this->scheme['upyun']['secret_key']);
+ $client = new Upyun($bucketConfig);
+ // 删除文件
+ $client->delete($file_info['path']);
+ // 删除目录
+ //$client->deleteDir(substr('/' . $file_info['path'], 0, strrpos($file_info['path'], '/')));
+ }
+ break;
+ case 4: // 删除阿里OSS文件
+ break;
+ }
+ Db::commit();
+ } catch (\Exception $e) {
+ Db::rollback();
+ return parent::json(0, "删除失败,{$e->getMessage()}");
+ }
+ return parent::json(1, "删除成功");
+ }
+ }
+
+ /**
+ * 批量删除
+ * @param $array
+ * @return \think\response\Json
+ */
+ public function batchDel($array)
+ {
+ if(Request::instance()->isAjax()) {
+ Db::startTrans();
+ try {
+ $file_db = Db::name('file');
+ foreach ($array as $val) {
+ $file_info = $file_db->where(['id' => $val])->find();
+ switch ((int)$file_info['scheme_id']) {
+ case 1: // 删除本地文件
+ @unlink("{$this->conf['file_path']}/{$file_info['path']}");
+ $file_db->where('id', $val)->delete();
+ break;
+ case 2: // 删除七牛云文件
+ $auth = new Auth($this->scheme['qiniu']['access_key'], $this->scheme['qiniu']['secret_key']);
+ $config = new \Qiniu\Config();
+ $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
+ $bucketManager->delete($this->scheme['qiniu']['bucket_name'], $file_info['path']);
+ $file_db->where('id', $val)->delete();
+ break;
+ case 3: // 删除又拍云文件
+ $file_db->where('id', $val)->delete();
+ // 创建实例
+ $bucketConfig = new \Upyun\Config($this->scheme['upyun']['bucket_name'], $this->scheme['upyun']['access_key'], $this->scheme['upyun']['secret_key']);
+ $client = new Upyun($bucketConfig);
+ $client->delete($file_info['path']);
+ // 删除目录
+ //$client->deleteDir(substr('/' . $file_info['path'], 0, strrpos($file_info['path'], '/')));
+ break;
+ case 4: // 删除阿里OSS文件
+ //$file_db->where('id', $val)->delete();
+ break;
+ }
+ }
+ Db::commit();
+ } catch (\Exception $e) {
+ Db::rollback();
+ return parent::json(0, "删除失败,{$e->getMessage()}");
+ }
+ return parent::json(1, '删除成功');
+ }
+ }
+
+ /**
+ * 根据ID获取用户用户名
+ * @param $id
+ * @return array|false|\PDOStatement|string|\think\Model
+ */
+ public function getUserName($id)
+ {
+ return Db::name('user')->where('id', $id)->value('username');
+ }
+
+}
diff --git a/app/admin/controller/System.php b/app/admin/controller/System.php
new file mode 100644
index 0000000..60d7a4d
--- /dev/null
+++ b/app/admin/controller/System.php
@@ -0,0 +1,83 @@
+isAjax()) {
+ $data = Request::instance()->post();
+ Db::startTrans();
+ try {
+ foreach ($data as $key => $val) {
+ Db::name('config')->where('key', $key)->update(['value' => $val, 'edit_time' => time()]);
+ }
+ Db::commit();
+ } catch (\Exception $e) {
+ Db::rollback();
+ return parent::json(0, '修改失败');
+ }
+ return parent::json(1, '修改成功');
+ }
+ $this->assign('scheme', getSchemeList());
+ return $this->fetch();
+ }
+
+ /**
+ * 修改上传方案配置
+ * @return \think\response\Json
+ */
+ public function setScheme()
+ {
+ if(Request::instance()->isAjax()) {
+ Db::startTrans();
+ try {
+ $input = Request::instance()->param();
+ $input['edit_time'] = time();
+ Db::name('config')->where('key', 'upload_scheme_id')->setField('value', $input['id']);
+ Db::name('scheme')->where('id', $input['id'])->update($input);
+ Db::commit();
+ } catch (\Exception $e) {
+ Db::rollback();
+ return parent::json(0, "Code: {$e->getCode()} Msg: {$e->getMessage()}");
+ }
+ return parent::json(1, '修改成功');
+ }
+ }
+
+ /**
+ * 发送测试Email
+ * @param $email
+ * @return \think\response\Json\
+ */
+ public function sendTestEmail($email)
+ {
+ if(Request::instance()->isAjax()) {
+ $smtp = new Smtp(
+ $this->conf['smtp_host'],
+ $this->conf['smtp_port'],
+ $this->conf['smtp_auth'],
+ $this->conf['smtp_user'],
+ $this->conf['smtp_pass'],
+ $this->conf['smtp_ssl']
+ );
+ $send = $smtp->send($email, $this->conf['smtp_user'], "「{$this->conf['web_title']}」", '这是一封测试邮件');
+ if($send) {
+ return parent::json(1, '发送成功');
+ } else {
+ return parent::json(0, '发送失败');
+ }
+ }
+ }
+}
diff --git a/app/admin/controller/Theme.php b/app/admin/controller/Theme.php
new file mode 100644
index 0000000..6403ff0
--- /dev/null
+++ b/app/admin/controller/Theme.php
@@ -0,0 +1,56 @@
+isAjax()) {
+ if(!empty($theme)) {
+ if(Db::name('config')->where('key', 'now_theme')->update(['value' => $theme, 'edit_time' => time()])) {
+ return parent::json(1, '成功');
+ }
+ return parent::json(0, '失败');
+ }
+ }
+ $theme = $this->getTheme($this->conf['theme_path']);
+ foreach ($theme as $key => $val) {
+ $data[$val] = Config::load("{$this->conf['theme_path']}/{$val}/config.php", '', 'Theme');
+ }
+ $this->assign('theme', $data);
+ return $this->fetch();
+ }
+
+ /**
+ * 获取所有主题文件夹
+ * @param $dir 父目录路径
+ * @return array
+ */
+ function getTheme($dir)
+ {
+ $subdirs = array();
+ if(!$dh = opendir($dir))
+ return $subdirs;
+ $i = 0;
+ while ($f = readdir($dh))
+ {
+ if($f =='.' || $f =='..')
+ continue;
+ $path = $f;
+ $subdirs[$i] = $path;
+ $i++;
+ }
+ return $subdirs;
+ }
+}
diff --git a/app/admin/controller/Users.php b/app/admin/controller/Users.php
new file mode 100644
index 0000000..af0a8b3
--- /dev/null
+++ b/app/admin/controller/Users.php
@@ -0,0 +1,59 @@
+fetch();
+ }
+
+ /**
+ * 分页获取会员
+ * @param int $page 页码
+ * @param int $limit 每页显示数量
+ * @param array $key 条件
+ * @return \think\response\Json
+ */
+ public function getUserList($page = 0, $limit = 0, array $key = [])
+ {
+ $map['id'] = ['neq', 1];
+ if(count($key) > 0) $map = $key;
+ $user_db = Db::name('user');
+ $user_list = $user_db->where($map)->order('reg_time desc')->page($page, $limit)->select();
+ foreach ($user_list as $key => &$val) {
+ $val['login_time'] = formatTime($val['login_time']);
+ $val['reg_time'] = date('Y-m-d h:i:s', $val['reg_time']);
+ unset($val['password']);
+ unset($val['edit_time']);
+ }
+ return parent::json(0, '', $user_list, '', $user_db->count());
+ }
+
+ /**
+ * 删除 And 批量删除会员
+ * @param $id
+ * @return \think\response\Json
+ * @throws \think\Exception
+ */
+ public function del($id)
+ {
+ if(Request::instance()->isAjax()) {
+ if(Db::name('user')->delete($id)) {
+ return parent::json(1, '删除成功');
+ }
+ return parent::json(0, '删除失败');
+ }
+ }
+
+}
diff --git a/app/admin/view/common/footer.html b/app/admin/view/common/footer.html
new file mode 100644
index 0000000..691287b
--- /dev/null
+++ b/app/admin/view/common/footer.html
@@ -0,0 +1,2 @@
+