Initial commit

This commit is contained in:
net909
2023-09-28 16:21:06 +08:00
parent 498772eb04
commit ba7be004c0
640 changed files with 87745 additions and 0 deletions
+220
View File
@@ -0,0 +1,220 @@
<?php
namespace app\controller;
use think\facade\Db;
use think\facade\Request;
use think\facade\Session;
use think\facade\View;
use app\lib\Oauth;
use think\helper\Str;
class Auth extends Base
{
public function login()
{
if(request()->islogin) {
return $this->alert('success', '已登录', '/');
}
View::assign(['is_qq'=>config_get('oauth_openqq'), 'is_wx'=>config_get('oauth_openxw')]);
return view();
}
private function oauth_config(){
return [
'apiurl' => config_get('oauth_appurl'),
'appid' => config_get('oauth_appid'),
'appkey' => config_get('oauth_appkey'),
'callback' => (string)url('/oauth/callback', [], '', true),
];
}
public function oauth()
{
$type = input('post.type');
if(!$type){
return msg('error', '登录方式不能为空');
}
$state = md5(uniqid(rand(), TRUE));
session('oauth_state', $state);
$oauth = new Oauth($this->oauth_config());
$res = $oauth->login($type, $state);
if(isset($res['code']) && $res['code']==0){
return msg('ok', 'success', $res['url']);
}else{
return msg('error', $res ? $res['msg'] : '登录地址获取失败');
}
}
public function callback()
{
$code = input('get.code');
$state = input('get.state');
if (empty($code)) {
return $this->alert('error', 'code不能为空', '/login');
}
if(!$state || $state != session('oauth_state')){
return $this->alert('error', 'state校验失败,请重新登录', '/login');
}
$oauth = new Oauth($this->oauth_config());
$res = $oauth->callback($code);
if(isset($res['code']) && $res['code']==0){
$type = $res['type'];
$openid = $res['social_uid'];
if(empty($res['nickname'])) $res['nickname'] = $type.Str::random(5);
$user = Db::name('user')->where('type', $type)->where('openid', $openid)->find();
if($user){
if($user['enable']==0){
session('user_block', '1');
return $this->alert('error', '当前用户已被禁止登录', '/');
}
$uid = $user['id'];
$password = $user['password'];
Db::name('user')->where('id', $uid)->update([
'avatar_url' => $res['faceimg'],
'loginip' => $this->clientip,
'update_time' => date('Y-m-d H:i:s')
]);
if(session('user_block') == '1'){
Db::name('user')->where('id', $uid)->update(['enable' => 0]);
return $this->alert('error', '当前用户已被禁止登录', '/');
}
}else{
$password = Str::random(16);
$uid = Db::name('user')->insertGetId([
'type' => $type,
'openid' => $openid,
'username' => $res['nickname'],
'password' => $password,
'avatar_url' => $res['faceimg'],
'regip' => $this->clientip,
'create_time' => date('Y-m-d H:i:s'),
'update_time' => date('Y-m-d H:i:s')
]);
if(session('user_block') == '1'){
Db::name('user')->where('id', $uid)->update(['enable' => 0]);
return $this->alert('error', '当前用户已被禁止登录', '/');
}
}
$session = md5($uid.$password);
$expiretime = time()+30744000;
$token = authcode("{$uid}\t{$session}\t{$expiretime}", 'ENCODE', config_get('syskey'));
cookie('user_token', $token, ['expire' => $expiretime, 'httponly' => true]);
session('oauth_state', null);
return redirect("/");
}else{
return $this->alert('error', $res ? $res['msg'] : '登录数据获取失败');
}
}
public function logout()
{
//session(null);
cookie('user_token', null);
return redirect(request()->header('referer') ?? '/');
}
public function verifycode()
{
return captcha();
}
public function adminlogin(){
$username = input('post.username',null,'trim');
$password = input('post.password',null,'trim');
$captcha = input('post.captcha',null,'trim');
if(empty($username) || empty($password)){
return msg('error', '用户名或密码不能为空');
}
if(!captcha_check($captcha)){
return msg('error', '验证码错误');
}
if($username == config_get('admin_username') && password_verify($password, config_get('admin_password'))){
$session = md5($username.config_get('admin_password'));
$expiretime = time()+2562000;
$token = authcode("{$username}\t{$session}\t{$expiretime}", 'ENCODE', config_get('syskey'));
cookie('admin_token', $token, ['expire' => $expiretime, 'httponly' => true]);
config_set('admin_lastlogin', date('Y-m-d H:i:s'));
return msg();
}else{
return msg('error', '用户名或密码错误');
}
}
public function adminlogout()
{
cookie('admin_token', null);
return redirect('/admin/login.html');
}
public function qqlogin_api(){
$do = input('get.do');
$type = input('get.type');
$info = $this->getQqloginInfo($type);
if(!$info){
return json(['saveOK'=>1, 'msg'=>'该登录类型不存在']);
}
$login = new \app\lib\QQLogin();
if($do == 'getqrpic'){
$array = $login->getqrpic($info[0]);
}
elseif($do == 'qrlogin'){
$array = $login->qrlogin($info[0], $info[1], input('get.qrsig'));
if($array['saveOK'] == 0){
$cookie = ['uin' => $array['uin'], 'cookie' => $array['cookie'], 'nickname' => $array['nickname']];
session('qq_cookie_'.$type, $cookie);
}
}
return json($array);
}
public function qqlogin(){
if(!checkRefererHost()){
return redirect('/');
}
$redirect = input('get.redirect');
$type = input('get.type');
if(!$redirect || !$type){
return $this->alert('error', '缺少参数', '/');
}
$info = $this->getQqloginInfo($type);
if(!$info){
return $this->alert('error', '该登录类型不存在', '/');
}
if (substr($redirect,0,1)!='/') {
return $this->alert('error', '回调地址错误', '/');
}
View::assign('logintype', base64_encode($type));
View::assign('loginname', base64_encode($info[2]));
View::assign('redirect', base64_encode($redirect));
return view();
}
private function getQqloginInfo($type){
switch($type){
case 'qzone':
return ['5','https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone', 'QQ空间'];
break;
case 'qun':
return ['73','https://qun.qq.com/', 'QQ群管理'];
break;
case 'qqid':
return ['1','https://id.qq.com/index.html' ,'我的QQ中心'];
break;
default:
return null;
break;
}
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace app\controller;
use app\BaseController;
use think\facade\View;
class Base extends BaseController
{
protected $clientip;
protected function initialize()
{
$this->clientip = real_ip(config_get('ip_type')??0);
parent::initialize();
}
protected function alert($code, $msg = '', $url = null, $wait = 3)
{
if ($url) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : (string)$this->app->route->buildUrl($url);
}
if(empty($msg)) $msg = '未知错误';
View::assign([
'code' => $code,
'msg' => $msg,
'url' => $url,
'wait' => $wait,
]);
return View::fetch(app()->getRootPath().'view/dispatch_jump.html');
}
}
+226
View File
@@ -0,0 +1,226 @@
<?php
namespace app\controller;
use think\facade\Db;
use think\facade\View;
use think\facade\Validate;
class Index extends Base
{
const CACHE_TIME = 0;
public function index()
{
$category = Db::name('category')->cache('categorys', self::CACHE_TIME)->field('id,title,icon')->where('enable', 1)->order('weight','desc')->select();
$link = Db::name('link')->cache('links', self::CACHE_TIME)->field('id,name,url')->where('enable', 1)->order('weight','desc')->select();
$tool = Db::name('plugin')->cache('plugins', self::CACHE_TIME)->field('id,title,alias,keyword,request_count,category_id,level')->where('enable', 1)->order('weight','desc')->select();
$list = [];
foreach($category as $item){
$list2 = [];
foreach($tool as $row){
if(!plugin_userlevel($row['level'])) continue;
if($row['category_id'] == $item['id']){
$row['url'] = get_plugin_url($row['alias']);
$row['out'] = substr($row['alias'],0,1) == '/' || substr($row['alias'],0,7) == 'http://' || substr($row['alias'],0,8) == 'https://';
$list2[] = $row;
}
}
$list[] = ['id'=>$item['id'], 'title'=>$item['title'], 'icon'=>$item['icon'], 'items'=>$list2];
}
View::assign('category', $category);
View::assign('tool', $list);
View::assign('link', $link);
return view();
}
public function stars()
{
if(request()->isAjax()){
if(!request()->islogin){
return msg('error', '登录后才能收藏工具');
}
$uid = request()->user['id'];
$do = input('post.do');
if($do == 'clear'){
Db::name('user')->where('id', $uid)->update(['stars'=>'']);
return msg();
}
$id = input('post.id/d');
if(empty($do) || empty($id)) return msg('error', 'param error');
$plugin = Db::name('plugin')->where('id', $id)->where('enable',1)->find();
if(!$plugin) return msg('error', '工具不存在');
$stars = explode(',',request()->user['stars']);
if ($do == 'add' && !in_array($id, $stars)) {
array_push($stars, $id);
} elseif ($do == 'del') {
if (($key = array_search($id, $stars)) !== false) {
unset($stars[$key]);
}
}
$stars = implode(',', array_unique(array_values($stars)));
Db::name('user')->where('id', $uid)->update(['stars'=>$stars]);
return msg('ok', $do == 'add' ? '添加收藏成功!' : '取消收藏成功!');
}
if(!request()->islogin){
return $this->alert('info', '请先登录', '/login');
}
$category = Db::name('category')->cache('categorys', self::CACHE_TIME)->field('id,title,icon')->where('enable', 1)->order('weight','desc')->select();
$list = [];
$stars = request()->user['stars'];
if(strlen($stars)>0){
$stars = explode(',',$stars);
$tool = Db::name('plugin')->cache('plugins', self::CACHE_TIME)->field('id,title,alias,keyword,request_count,category_id')->where('enable', 1)->order('weight','desc')->select();
$list = [];
foreach($category as $item){
foreach($tool as $row){
if(!plugin_userlevel($row['level'])) continue;
if($row['category_id'] == $item['id'] && in_array($row['id'],$stars)){
$row['url'] = get_plugin_url($row['alias']);
$row['out'] = substr($row['alias'],0,1) == '/' || substr($row['alias'],0,7) == 'http://' || substr($row['alias'],0,8) == 'https://';
$list[] = $row;
}
}
}
}
View::assign('category', $category);
View::assign('tool', $list);
return view();
}
public function history()
{
if(request()->isAjax()){
$do = input('post.do');
if($do == 'clear'){
cookie('tools', null);
return msg();
}
}
$category = Db::name('category')->cache('categorys', self::CACHE_TIME)->field('id,title,icon')->where('enable', 1)->order('weight','desc')->select();
$list = [];
$history = cookie('tools');
if(strlen($history)>0){
$history = array_reverse(array_unique(explode(',',$history)));
$tool = Db::name('plugin')->cache('plugins', self::CACHE_TIME)->field('id,title,alias,keyword,request_count,category_id')->where('enable', 1)->order('weight','desc')->select();
$newtool = [];
foreach($tool as $row){
$newtool[$row['id']] = $row;
}
$list = [];
foreach($history as $id){
$row = $newtool[$id];
if(!$row) continue;
if(!plugin_userlevel($row['level'])) continue;
$row['url'] = get_plugin_url($row['alias']);
$row['out'] = substr($row['alias'],0,1) == '/' || substr($row['alias'],0,7) == 'http://' || substr($row['alias'],0,8) == 'https://';
$list[] = $row;
}
}
View::assign('category', $category);
View::assign('tool', $list);
return view();
}
public function comment(){
if(request()->isAjax()){
$do = input('param.do');
if($do == 'add'){
if(!request()->islogin){
return msg('error', '登录后才能提交留言');
}
$email = input('post.email', null, 'trim,strip_tags,htmlspecialchars');
$content = input('post.content', null, 'trim,strip_tags,htmlspecialchars');
$data = [
'uid' => request()->user['id'],
'email' => $email,
'content' => $content,
'enable' => 0,
'create_time' => date("Y-m-d H:i:s"),
'update_time' => date("Y-m-d H:i:s")
];
$validate = Validate::rule([
'email|电子邮箱' => 'require|email',
'content|留言内容' => 'require',
]);
if (!$validate->check($data)) {
return msg('error', $validate->getError());
}
$captcha_result = verify_captcha4_slide();
if($captcha_result !== true){
return msg('error', $captcha_result);
}
$last = Db::name('comment')->where('uid', request()->user['id'])->order('id','desc')->find();
if($last && time() - strtotime($last['create_time']) < 600){
return msg('error', '你发表留言的速度太快了,过段时间再来吧');
}
Db::name('comment')->insert($data);
return msg();
}else{
$page = input('get.page/d');
$limit = 5;
$uid = request()->islogin ? request()->user['id'] : 0;
$select = Db::name('comment')->alias('A')->leftJoin('user B', 'A.uid=B.id')->field('A.id,A.uid,content,reply,A.enable,A.create_time,A.update_time,B.username,B.avatar_url')->where('A.enable', 1)->whereOr('A.uid', $uid);
$total = $select->count();
$comment = $select->order('id','desc')->page($page, $limit)->select();
$items = [];
foreach($comment as $item){
if(!$item['avatar_url']) $item['avatar_url'] = '/static/images/user.png';
$item['time'] = dgmdate($item['create_time']);
$items[] = $item;
}
return msg('ok', 'success', ['total'=>$total, 'page'=>$page, 'pagenum'=>ceil($total/$limit), 'items'=>$items]);
}
}
return view();
}
public function captcha(){
$GtSdk = new \app\lib\GeetestLib(config_get('captcha_id'), config_get('captcha_key'));
$data = array(
'user_id' => request()->islogin?request()->user['id']:'public',
'client_type' => "web",
'ip_address' => $this->clientip
);
$result = $GtSdk->pre_process($data);
session('gtserver', $result['success']);
return json($result);
}
public function statistics(){
$id = input('post.id/d');
if(!$id) return msg('error', 'param error');
$plugin = Db::name('plugin')->where('id', $id)->where('enable', 1)->find();
if(!$plugin) return msg('error', '工具不存在');
Db::name('plugin')->where('id', $id)->inc('request_count')->update();
$history = cookie('tools');
if(!$history) $history = [];
else $history = array_unique(explode(',',$history));
if(in_array($id, $history)){
$key = array_search($id,$history);
unset($history[$key]);
}
$history[] = $id;
if(count($history) > 20){
$history = array_splice($history, 0, 20);
}
cookie('tools', implode(',', $history));
return msg();
}
}
+131
View File
@@ -0,0 +1,131 @@
<?php
namespace app\controller;
use app\lib\EnvOperation;
use app\lib\ExecSQL;
use PDO;
use think\Exception;
use think\facade\Cache;
use think\facade\Request;
use think\facade\Validate;
use think\facade\View;
use think\helper\Str;
class Install extends Base
{
public function __destruct()
{
Cache::clear();
reset_opcache();
}
public function initialize()
{
// 检测是否已安装
if (file_exists(app()->getRootPath() . 'install.lock')) {
exit('你已安装成功,需要重新安装请删除 install.lock 文件');
}
Cache::clear();
reset_opcache();
}
public function index()
{
// 检查安装环境
$requirements = [
'PHP >= 7.4' => PHP_VERSION >= 7.4,
'PDO_MySQL' => extension_loaded("pdo_mysql"),
'CURL' => extension_loaded("curl"),
'ZipArchive' => class_exists("ZipArchive"),
'runtime写入权限' => is_writable(app()->getRuntimePath()),
];
reset_opcache();
$step = Request::param('step');
View::assign([
'step' => $step,
'requirements' => $requirements,
]);
return view('../view/install/index.html');
}
public function database()
{
$params = Request::param();
$rules = [
'hostname' => 'require',
'hostport' => 'require|integer',
'username' => 'require',
'password' => 'require',
'database' => 'require',
];
$validate = Validate::rule($rules);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$dsn = 'mysql:host=' . $params['hostname'] . ';dbname=' . $params['database'] . ';port=' . $params['hostport'] . ';charset=utf8';
try {
new PDO($dsn, $params['username'], $params['password']);
} catch (\Exception $e) {
return msg('error', $e->getMessage());
}
try {
$envFile = file_get_contents(app()->getRootPath() . '.env.example');
$envOperation = new EnvOperation($envFile);
foreach (array_keys($rules) as $value) {
$envOperation->set(mb_strtoupper($value), $params[$value]);
}
$envOperation->save();
} catch (\Exception $e) {
return msg('error', $e->getMessage());
}
return msg();
}
public function init_data()
{
try {
$filename = app()->getRootPath() . 'install.sql';
if (!is_file($filename)) {
throw new Exception('数据库 install.sql 文件不存在');
}
$install_sql = file($filename);
//写入数据库
$execSQL = new ExecSQL();
$install_sql = $execSQL->purify($install_sql);
foreach ($install_sql as $sql) {
$execSQL->exec($sql);
if (!empty($execSQL->getErrors())) {
throw new Exception($execSQL->getErrors()[0]);
}
}
} catch (\Exception $e) {
return msg('error', $e->getMessage());
}
return msg();
}
public function admin()
{
$params = Request::param();
$rules = [
'username|用户名' => 'require',
'password|密码' => 'require',
];
$validate = Validate::rule($rules);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
config_set("admin_username", $params['username']);
config_set("admin_password", password_hash($params['password'], PASSWORD_DEFAULT));
config_set("syskey", Str::random(16));
file_put_contents(app()->getRootPath() . 'install.lock', format_date());
return msg();
}
}
+134
View File
@@ -0,0 +1,134 @@
<?php
namespace app\controller\admin;
use app\controller\Base;
use think\facade\Request;
use think\facade\Validate;
use think\facade\Db;
class Category extends Base
{
public function list()
{
$params = Request::param();
$validate = Validate::rule([
'page' => 'integer',
'limit' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$page = isset($params['page']) ? intval($params['page']) : 1;
$limit = isset($params['limit']) ? intval($params['limit']) : 50;
$select = Db::name('category');
if(!empty($params['title'])){
$select->where('title', 'like', '%' . $params['title'] . '%');
}
$total = $select->count();
$items = $select->order('weight','desc')->page($page, $limit)->select();
return msg("ok", "success", ['total'=>$total, 'items'=>$items]);
}
public function get()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$item = Db::name('category')->where('id', $params['id'])->findOrEmpty();
return msg('ok', 'success', $item);
}
public function add()
{
$params = Request::param();
$validate = Validate::rule([
'title|分类标题' => 'require|unique:category',
'icon|小图标' => 'require',
'weight|权重' => 'require|integer',
'enable' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('category')->cache('categorys')->insert([
'title' => trim($params['title']),
'icon' => trim($params['icon']),
'weight' => $params['weight'],
'enable' => $params['enable'],
'create_time' => date("Y-m-d H:i:s"),
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function edit()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require',
'icon|小图标' => 'require',
'title|分类标题' => 'require|unique:category',
'weight|权重' => 'require|integer',
'enable' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('category')->cache('categorys')->where('id', $params['id'])->update([
'title' => trim($params['title']),
'icon' => trim($params['icon']),
'weight' => $params['weight'],
'enable' => $params['enable'],
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function enable()
{
$id = input('post.id/d');
$enable = input('post.enable/d');
Db::name('category')->cache('categorys')->where('id', $id)->update([
'enable' => $enable,
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function delete()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('category')->cache('categorys')->where('id', $params['id'])->delete();
return msg();
}
}
+140
View File
@@ -0,0 +1,140 @@
<?php
namespace app\controller\admin;
use app\controller\Base;
use think\facade\Request;
use think\facade\Validate;
use think\facade\Db;
class Comment extends Base
{
public function list()
{
$params = Request::param();
$validate = Validate::rule([
'page' => 'integer',
'limit' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$page = intval($params['page']);
$limit = intval($params['limit']);
$select = Db::name('comment');
if(!empty($params['uid'])){
$select->where('uid', $params['uid']);
}
if(!empty($params['content'])){
$select->where('content', 'like', '%' . $params['content'] . '%');
}
$total = $select->count();
$items = $select->order('id','desc')->page($page, $limit)->select();
return msg("ok", "success", ['total'=>$total, 'items'=>$items]);
}
public function get()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$item = Db::name('comment')->where('id', $params['id'])->findOrEmpty();
return msg('ok', 'success', $item);
}
public function edit()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require',
'content|留言内容' => 'require',
'enable' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('comment')->where('id', $params['id'])->update([
'content' => $params['content'],
'reply' => $params['reply'],
'enable' => $params['enable'],
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function enable()
{
$id = input('post.id/d');
$enable = input('post.enable/d');
Db::name('comment')->where('id', $id)->update([
'enable' => $enable,
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function delete()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('comment')->where('id', $params['id'])->delete();
return msg();
}
public function uploadlog()
{
$params = Request::param();
$validate = Validate::rule([
'page' => 'integer',
'limit' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$page = intval($params['page']);
$limit = intval($params['limit']);
$select = Db::name('uploadlog');
if(!empty($params['uid'])){
$select->where('uid', $params['uid']);
}
if(!empty($params['ip'])){
$select->where('ip', $params['ip']);
}
if(!empty($params['fileurl'])){
$select->where('fileurl', $params['fileurl']);
}
$total = $select->count();
$items = $select->order('id','desc')->page($page, $limit)->select();
return msg("ok", "success", ['total'=>$total, 'items'=>$items]);
}
}
+134
View File
@@ -0,0 +1,134 @@
<?php
namespace app\controller\admin;
use app\controller\Base;
use think\facade\Request;
use think\facade\Validate;
use think\facade\Db;
class Link extends Base
{
public function list()
{
$params = Request::param();
$validate = Validate::rule([
'page' => 'integer',
'limit' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$page = intval($params['page']);
$limit = intval($params['limit']);
$select = Db::name('link');
if(!empty($params['keyword'])){
$select->where('name|url', 'like', '%' . $params['keyword'] . '%');
}
$total = $select->count();
$items = $select->order('weight','desc')->page($page, $limit)->select();
return msg("ok", "success", ['total'=>$total, 'items'=>$items]);
}
public function get()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$item = Db::name('link')->where('id', $params['id'])->findOrEmpty();
return msg('ok', 'success', $item);
}
public function add()
{
$params = Request::param();
$validate = Validate::rule([
'name|名称' => 'require|chsAlphaNum|unique:link',
'url|地址' => 'require',
'weight|权重' => 'require|integer',
'enable' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('link')->cache('links')->insert([
'name' => trim($params['name']),
'url' => trim($params['url']),
'weight' => $params['weight'],
'enable' => $params['enable'],
'create_time' => date("Y-m-d H:i:s"),
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function edit()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require',
'name|名称' => 'require|chsAlphaNum|unique:link',
'url|地址' => 'require',
'weight|权重' => 'require|integer',
'enable' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('link')->cache('links')->where('id', $params['id'])->update([
'name' => trim($params['name']),
'url' => trim($params['url']),
'weight' => $params['weight'],
'enable' => $params['enable'],
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function enable()
{
$id = input('post.id/d');
$enable = input('post.enable/d');
Db::name('link')->cache('links')->where('id', $id)->update([
'enable' => $enable,
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function delete()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('link')->cache('links')->where('id', $params['id'])->delete();
return msg();
}
}
+120
View File
@@ -0,0 +1,120 @@
<?php
namespace app\controller\admin;
use app\BaseController;
class Menu extends BaseController
{
public function get(){
$homeInfo = [
'title' => '主页',
'href' => 'page/dashboard.html',
];
$logoInfo = [
'title' => '工具网后台',
'image' => 'images/logo.png',
'href' => './',
];
$menuInfo = [
[
"title" => "常规管理",
"icon" => "fa fa-address-book",
"href" => "",
"target" => "_self",
"child" => [
[
"title" => "主页",
"icon" => "fa fa-home",
"target" => "_self",
"href" => "page/dashboard.html",
],
[
"title" => "分类管理",
"href" => "page/category.html",
"icon" => "fa fa-bookmark-o",
"target" => "_self",
],
[
"title" => "插件管理",
"href" => "",
"icon" => "fa fa-puzzle-piece",
"target" => "_self",
"child" => [
[
"title" => "插件列表",
"href" => "page/plugin.html",
"icon" => "fa fa-list",
"target" => "_self"
],
[
"title" => "安装新插件",
"href" => "page/plugin/install.html",
"icon" => "fa fa-cloud-upload",
"target" => "_self"
],
]
],
[
"title" => "用户管理",
"href" => "page/user.html",
"icon" => "fa fa-user",
"target" => "_self",
],
[
"title" => "留言管理",
"href" => "page/comment.html",
"icon" => "fa fa-comments",
"target" => "_self",
],
[
"title" => "上传记录",
"href" => "page/uploadlog.html",
"icon" => "fa fa-cloud-upload",
"target" => "_self",
],
[
"title" => "友链管理",
"href" => "page/link.html",
"icon" => "fa fa-link",
"target" => "_self",
],
[
"title" => "系统配置",
"href" => "",
"icon" => "fa fa-cogs",
"target" => "_self",
"child" => [
[
"title" => "基本信息配置",
"href" => "page/system.html",
"icon" => "fa fa-cog",
"target" => "_self"
],
[
"title" => "管理员配置",
"href" => "page/account.html",
"icon" => "fa fa-user",
"target" => "_self"
],
]
],
/*[
"title" => "在线升级",
"href" => "page/update.html",
"icon" => "fa fa-cloud-upload",
"target" => "_self",
],*/
],
]
];
$systemInit = [
'homeInfo' => $homeInfo,
'logoInfo' => $logoInfo,
'menuInfo' => $menuInfo,
];
return json($systemInit);
}
}
+224
View File
@@ -0,0 +1,224 @@
<?php
namespace app\controller\admin;
use app\BaseController;
use think\facade\Db;
use think\facade\Request;
use think\facade\Session;
use think\facade\Validate;
class Plugin extends BaseController
{
public function list()
{
$params = Request::param();
$validate = Validate::rule([
'page' => 'integer',
'limit' => 'integer',
'category_id' => 'integer',
'class' => 'is_legal_plugin_class',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$page = isset($params['page']) ? intval($params['page']) : 1;
$limit = isset($params['limit']) ? intval($params['limit']) : 50;
$orderby = ['id' => 'desc'];
$select = Db::name('plugin');
if(!empty($params['title'])){
$select->where('title', 'like', '%' . $params['title'] . '%');
}
if(!empty($params['alias'])){
$select->where('alias', $params['alias']);
}
if(!empty($params['class'])){
$select->where('class', $params['class']);
}
if(!empty($params['enable'])){
$select->where('enable', '1');
}
if(!empty($params['category_id'])){
$select->where('category_id', $params['category_id']);
$orderby = ['weight' => 'desc', 'id' => 'desc'];
}
$total = $select->count();
$items = $select->order($orderby)->page($page, $limit)->select();
return msg("ok", "success", ['total'=>$total, 'items'=>$items]);
}
public function get()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$item = Db::name('plugin')->where('id', $params['id'])->findOrEmpty();
return msg('ok', 'success', $item);
}
public function add()
{
$params = Request::param();
$validate = Validate::rule([
'title|插件标题' => 'require|unique:plugin',
'alias|路由别名' => 'require|unique:plugin',
'class|插件类名' => 'require|unique:plugin|is_legal_plugin_class',
'category_id|分类' => 'require|integer',
'level|用户等级限制' => 'integer',
'enable' => 'integer',
'weight|权重' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('plugin')->cache('plugins')->insert([
'title' => trim($params['title']),
'alias' => trim($params['alias']),
'class' => trim($params['class']),
'keyword' => trim($params['keyword']),
'weight' => $params['weight'],
'enable' => $params['enable'],
'category_id' => $params['category_id'],
'level' => $params['level'],
'login' => $params['login'],
'desc' => $params['desc'],
'create_time' => date("Y-m-d H:i:s"),
'update_time' => date("Y-m-d H:i:s")
]);
return msg();
}
public function edit()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require',
'title|插件标题' => 'require|unique:plugin',
'alias|路由别名' => 'unique:plugin',
'class|插件类名' => 'unique:plugin|is_legal_plugin_class',
'category_id|分类' => 'integer',
'level|用户等级限制' => 'integer',
'enable' => 'integer',
'weight|权重' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
if(isset($params['level']) && isset($params['enable'])){
Db::name('plugin')->cache('plugins')->where('id', $params['id'])->update([
'title' => trim($params['title']),
'alias' => trim($params['alias']),
'class' => trim($params['class']),
'keyword' => trim($params['keyword']),
'weight' => $params['weight'],
'enable' => $params['enable'],
'category_id' => $params['category_id'],
'level' => $params['level'],
'login' => $params['login'],
'desc' => $params['desc'],
'update_time' => date("Y-m-d H:i:s")
]);
}else{
Db::name('plugin')->cache('plugins')->where('id', $params['id'])->update([
'title' => trim($params['title']),
'alias' => trim($params['alias']),
'class' => trim($params['class']),
'category_id' => $params['category_id'],
'desc' => $params['desc'],
'update_time' => date("Y-m-d H:i:s")
]);
}
return msg();
}
public function enable(){
$params = Request::param();
$validate = Validate::rule([
'id' => 'require',
'category_id|分类' => 'integer',
'enable' => 'integer'
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('plugin')->cache('plugins')->where('id', $params['id'])->update($params);
return msg();
}
public function delete()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$plugin = Db::name('plugin')->where('id', $params['id'])->find();
if(!$plugin) return msg('ok', 'success');
Db::startTrans();
try {
$classPath = plugin_path_get() . '/'.$plugin['class'].'/Install.php';
if (file_exists($classPath)) {
require $classPath;
$class = 'plugin\\'.$plugin['class'].'\\Install';
if (class_exists($class)) {
$uninstall = new $class();
$uninstall->UnInstall();
}
}
Db::name('plugin')->cache('plugins')->where('id', $params['id'])->delete();
if (!empty($plugin['class'])) {
del_tree(plugin_path_get($plugin['class']));
}
// 提交事务
Db::commit();
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
return msg('error', $e->getMessage(), $e);
}
return msg('ok', 'success');
}
public function upload()
{
$params = Request::file();
$validate = Validate::rule([
'file' => 'require|file',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$uploadedFile = Request::file('file');
$plugin = new \app\lib\Plugin();
$zipFilepath = $plugin->getZipFilepath();
$uploadedFile->move(dirname($zipFilepath), basename($zipFilepath));
return $plugin->install();
}
}
+127
View File
@@ -0,0 +1,127 @@
<?php
namespace app\controller\admin;
use app\BaseController;
use think\facade\Db;
use think\facade\Request;
use think\facade\Validate;
use think\facade\Cache;
class System extends BaseController
{
public function analysis(){
$data['count1'] = Db::name('plugin')->count();
$data['count2'] = Db::name('comment')->count();
$data['count3'] = Db::name('user')->count();
$data['count4'] = Db::name('user')->whereDay('create_time', date("Y-m-d"))->count();
return msg('ok', 'success', $data);
}
public function info()
{
$tmp = 'version()';
$mysqlVersion = Db::query("select version()")[0][$tmp];
$data = [
'framework_version' => app()::VERSION,
'php_version' => PHP_VERSION,
'mysql_version' => $mysqlVersion,
'software' => $_SERVER['SERVER_SOFTWARE'],
'os' => php_uname(),
'date' => date("Y-m-d H:i:s"),
'checkupdate' => '//auth.cccyun.cc/app/tool.php?version='.config('app.version').'&ver='.config('app.ver')
];
return msg('ok', 'success', $data);
}
public function all()
{
$all = Db::name('config')->select();
return msg('ok', 'success', $all);
}
public function get()
{
$key = Request::param('key');
$value = config_get($key);
return msg('ok', 'success', $value);
}
public function set()
{
$params = Request::param();
foreach ($params as $v) {
if (empty($v['key'])) {
continue;
}
config_set($v['key'], $v['value']);
}
cache('configs', NULL);
$all = Db::name('config')->select();
return msg('ok', 'success', $all);
}
public function setpwd()
{
$params = Request::param();
if(isset($params['username']))$params['username']=trim($params['username']);
if(isset($params['oldpwd']))$params['oldpwd']=trim($params['oldpwd']);
if(isset($params['newpwd']))$params['newpwd']=trim($params['newpwd']);
if(isset($params['newpwd2']))$params['newpwd2']=trim($params['newpwd2']);
$validate = Validate::rule([
'username|用户名' => 'require|chsAlphaNum',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
config_set('admin_username', $params['username']);
if(!empty($params['oldpwd']) && !empty($params['newpwd']) && !empty($params['newpwd2'])){
$oldpwd = config_get('admin_password');
if($oldpwd && !password_verify($params['oldpwd'], $oldpwd)){
return msg('error', '旧密码不正确');
}
if($params['newpwd'] != $params['newpwd2']){
return msg('error', '两次新密码输入不一致');
}
config_set('admin_password', password_hash($params['newpwd'], PASSWORD_DEFAULT));
}
cache('configs', NULL);
cookie('admin_token', null);
return msg();
}
public function templates()
{
$glob = glob(app()->getRootPath() . config("view.view_dir_name") . '/index/*');
$arr = [];
foreach ($glob as $v) {
if (is_dir($v)) {
array_push($arr, basename($v));
}
}
return msg('ok', 'success', $arr);
}
public function clear(){
Cache::clear();
reset_opcache();
return msg();
}
public function iptype(){
$result = [
['name'=>'0_X_FORWARDED_FOR', 'ip'=>real_ip(0), 'city'=>get_ip_city(real_ip(0))],
['name'=>'1_X_REAL_IP', 'ip'=>real_ip(1), 'city'=>get_ip_city(real_ip(1))],
['name'=>'2_REMOTE_ADDR', 'ip'=>real_ip(2), 'city'=>get_ip_city(real_ip(2))]
];
return msg('ok', 'success', $result);
}
}
+134
View File
@@ -0,0 +1,134 @@
<?php
namespace app\controller\admin;
use app\controller\Base;
use app\lib\ExecSQL;
use think\facade\Request;
class Update extends Base
{
private $RELEASE_API = '';
public function initialize()
{
reset_opcache();
$this->RELEASE_API = base64_decode('aHR0cHM6Ly90b29sLWNsb3VkLmFvYW9zdGFyLmNvbS9vcGVuL3JlbGVhc2U=');
}
private function get_last_release()
{
$res = get_curl($this->RELEASE_API, 0, Request::domain());
$json = json_decode($res);
if (empty($json) || empty($json->data)) {
if (!empty($json->message)) {
throw new \Exception($json->message);
}
throw new \Exception('"连接云中心失败,请检查网络连通性是否正常"');
}
return $json;
}
public function check()
{
try {
$release = $this->get_last_release();
$release->data->current_version = get_version();
} catch (\Exception $e) {
return msg('error', $e->getMessage());
}
return msg('ok', 'success', $release->data);
}
public function update()
{
try {
$release = $this->get_last_release();
} catch (\Exception $e) {
return msg('error', $e->getMessage());
}
$get = get_curl($release->data->download_url);
if (empty($get) || str_starts_with($get, 'CURL Error:')) {
return msg('error', '下载更新包失败,请检查网络连通性是否正常');
}
$tmpFilename = app()->getRuntimePath() . '/tmp/' . uniqid() . '.zip';
if (!file_exists(dirname($tmpFilename))) {
mkdir(dirname($tmpFilename), 0777, true);
}
if (!file_put_contents($tmpFilename, $get)) {
return msg('error', '保存文件失败,请检查是否有写入权限');
}
$rootPath = app()->getRootPath();
if (!unzip($tmpFilename, $rootPath)) {
return msg('error', '解压压缩包失败');
}
return msg('ok', '资源包解压成功', $release->data);
}
public function updateDatabase()
{
$glob = glob(app()->getRuntimePath() . '/update/sql/*.sql');
if (empty($glob)) {
return msg('ok', '未发现数据库更新文件');
}
foreach ($glob as $value) {
$result[$value] = [];
$basename = basename($value);
$lines = file($value);
$execSQL = new ExecSQL();
$lines = $execSQL->purify($lines);
$number = $execSQL->exec($lines);
$result[$value] = array_merge($result[$value], $execSQL->getErrors());
if ($number > 0) {
$result[$value][] = "影响的记录数 $number";
}
$result[$value][] = '创建数据库升级记录成功';
end:
unlink($value);
$result[$value] = "[$basename]" . implode("\n", $result[$value]);
}
return msg('ok', "数据库执行结果:\n" . implode("\n", $result));
}
public function updateScript()
{
$glob = glob(app()->getRuntimePath() . '/update/script/*.php');
if (empty($glob)) {
return msg('ok', '未发现更新脚本');
}
foreach ($glob as $value) {
$result[$value] = [];
$basename = basename($value);
try {
require $value;
$class = 'UpdateScript';
if (!class_exists($class)) {
throw new \Exception("更新脚本不存在[$class]类");
}
$instance = new $class();
$boot = 'main';
if (!method_exists($instance, $boot)) {
throw new \Exception("更新脚本不存在[$boot]方法");
}
$instance->main();
$result[$value] = array_merge($result[$value], $instance->getResult());
} catch (\Exception $e) {
$result[$value][] = $e->getMessage();
}
$result[$value][] = '创建更新脚本升级记录成功';
end:
unlink($value);
$result[$value] = "[$basename]" . implode("\n", $result[$value]);
}
return msg('ok', "更新脚本执行结果:\n" . implode("\n", $result));
}
}
+122
View File
@@ -0,0 +1,122 @@
<?php
namespace app\controller\admin;
use app\controller\Base;
use think\facade\Request;
use think\facade\Validate;
use think\facade\Db;
class User extends Base
{
public function list()
{
$params = Request::param();
$validate = Validate::rule([
'page' => 'integer',
'limit' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$page = intval($params['page']);
$limit = intval($params['limit']);
$select = Db::name('user');
if(!empty($params['id'])){
$select->where('id|openid', $params['id']);
}
if(!empty($params['username'])){
$select->where('username', 'like', '%' . $params['username'] . '%');
}
$total = $select->count();
$items = $select->order('id','desc')->page($page, $limit)->select();
return msg("ok", "success", ['total'=>$total, 'items'=>$items]);
}
public function get()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
$item = Db::name('user')->where('id', $params['id'])->findOrEmpty();
return msg('ok', 'success', $item);
}
public function enable(){
$params = Request::param();
$validate = Validate::rule([
'id' => 'require',
'enable' => 'integer'
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('user')->where('id', $params['id'])->update($params);
return msg();
}
public function edit()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require',
'level' => 'integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('user')->where('id', $params['id'])->update([
'level' => $params['level']
]);
return msg();
}
public function delete()
{
$params = Request::param();
$validate = Validate::rule([
'id' => 'require|integer',
]);
if (!$validate->check($params)) {
return msg('error', $validate->getError());
}
Db::name('user')->where('id', $params['id'])->delete();
return msg('ok', 'success');
}
public function slogin(){
$id = input('get.id/d');
$item = Db::name('user')->where('id', $id)->find();
if(!$item){
return $this->alert('error', '用户不存在');
}
$session = md5($id.$item['password']);
$expiretime = time()+30744000;
$token = authcode("{$id}\t{$session}\t{$expiretime}", 'ENCODE', config_get('syskey'));
cookie('user_token', $token, ['expire' => $expiretime, 'httponly' => true]);
return redirect("/");
}
}