优化插件系统

This commit is contained in:
taoser 2022-11-27 23:13:06 +08:00
parent 6cf239b1cf
commit b147198b0c
14 changed files with 510 additions and 204 deletions

View File

@ -31,17 +31,19 @@ class Addons extends AdminController
*/ */
public function addonsList() public function addonsList()
{ {
$data = Request::param();
$res = [];
//本地插件列表
$addonsList = Files::getDirName('../addons/');
$url = $this->getSystem()['api_url'].'/v1/addons';
$addons = Api::urlGet($url);
$type = input('type'); switch($data['type']){
$data = Request::only(['page', 'limit']);
$res = [];
switch($type){
//已安装 //已安装
case 'installed': case 'installed':
$addons = Files::getDirName('../addons/'); if($addonsList){
if($addons){
$res = ['code'=>0,'msg'=>'','count'=>5]; $res = ['code'=>0,'msg'=>'','count'=>5];
foreach($addons as $v){ foreach($addonsList as $v){
$info_file = '../addons/'.$v.'/info.ini'; $info_file = '../addons/'.$v.'/info.ini';
$info = parse_ini_file($info_file); $info = parse_ini_file($info_file);
$info['show'] = $info['status'] ? '启用' : '禁用'; $info['show'] = $info['status'] ? '启用' : '禁用';
@ -52,7 +54,7 @@ class Addons extends AdminController
['type' => 'numbers'], ['type' => 'numbers'],
['field' => 'name','title'=> '插件', 'width'=> 120], ['field' => 'name','title'=> '插件', 'width'=> 120],
['field'=> 'title','title'=> '标题', 'width'=> 100], ['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 60], ['field'=> 'version','title'=> '版本', 'templet' => '<div>{{d.version}}</div>', 'width'=> 60],
['field' => 'author','title'=> '作者', 'width'=> 80], ['field' => 'author','title'=> '作者', 'width'=> 80],
['field' => 'description','title'=> '简介', 'minWidth'=> 200], ['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'show','title'=> '状态', 'width'=> 100], ['field' => 'show','title'=> '状态', 'width'=> 100],
@ -64,14 +66,54 @@ class Addons extends AdminController
$res = ['code'=>-1,'msg'=>'没有安装任何插件']; $res = ['code'=>-1,'msg'=>'没有安装任何插件'];
} }
break; break;
//在线 //在线全部
case 'onlineAddons': case 'onlineAddons':
$url = $this->getSystem()['api_url'].'/v1/addons';
$addons = Api::urlGet($url);
if( $addons->code !== -1){ if( $addons->code !== -1){
// 与本地文件对比
foreach($addons->data as $v){
switch ($data['selector']) {
case 'free':
if($v->price == 0) {
if(in_array($v->name,$addonsList)) {
$info = get_addons_info($v->name);
//已安装
$v->isInstall = 1;
//判断是否有新版本
if($v->version > $info['version']) $v->have_newversion = 1;
$v->price = $v->price ? $v->price : '免费';
}
$res['data'][] = $v;
}
break;
case 'pay':
if($v->price > 0) {
if(in_array($v->name,$addonsList)) {
$info = get_addons_info($v->name);
//已安装
$v->isInstall = 1;
//判断是否有新版本
if($v->version > $info['version']) $v->have_newversion = 1;
$v->price = $v->price ? $v->price : '免费';
}
$res['data'][] = $v;
}
break;
case 'all':
if(in_array($v->name,$addonsList)) {
$info = get_addons_info($v->name);
//已安装
$v->isInstall = 1;
//判断是否有新版本
if($v->version > $info['version']) $v->have_newversion = 1;
$v->price = $v->price ? $v->price : '免费';
}
$res['data'][] = $v;
break;
}
};
$res['code'] = 0; $res['code'] = 0;
$res['msg'] = ''; $res['msg'] = '';
$res['data'] = $addons->data;
$res['col'] = [ $res['col'] = [
['type' => 'numbers'], ['type' => 'numbers'],
['field' => 'title','title'=> '插件', 'width'=> 200], ['field' => 'title','title'=> '插件', 'width'=> 200],
@ -79,14 +121,13 @@ class Addons extends AdminController
['field' => 'author','title'=> '作者', 'width'=> 100], ['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'price','title'=> '价格(元)','width'=> 80], ['field' => 'price','title'=> '价格(元)','width'=> 80],
['field' => 'downloads','title'=> '下载', 'width'=> 70], ['field' => 'downloads','title'=> '下载', 'width'=> 70],
['field' => 'version','title'=> '版本', 'width'=> 70], ['field' => 'version','title'=> '版本', 'templet' => '<div>{{d.version}} {{# if(d.have_newversion == 1){ }}<span class="layui-badge-dot"></span>{{# } }}</div>','width'=> 70],
['field' => 'status','title'=> '状态', 'width'=> 70], ['field' => 'status','title'=> '状态', 'width'=> 70],
['title' => '操作', 'width'=> 150, 'align'=>'center', 'toolbar'=> '#addons-tool'] ['title' => '操作', 'width'=> 150, 'align'=>'center', 'toolbar'=> '#addons-tool']
]; ];
} else { } else {
$res = ['code'=>-1,'msg'=>'未获取到服务器信息']; $res = ['code'=>-1,'msg'=>'未获取到服务器信息'];
} }
break; break;
} }
return json($res); return json($res);
@ -181,10 +222,10 @@ class Addons extends AdminController
//安装插件 //安装插件
public function install() public function install()
{ {
$data = Request::param(); $data = Request::param();
$url = $this->getSystem()['api_url'].'/v1/getaddons'; $url = $this->getSystem()['api_url'].'/v1/getaddons';
$addons = Api::urlPost($url,['name'=>$data['name'],'version'=>$data['version']]); $data = ['name'=>$data['name'], 'version'=>$data['version'], 'uid'=>$data['uid'], 'token'=>$data['token']];
$addons = Api::urlPost($url,$data);
if( $addons->code == -1) { if( $addons->code == -1) {
return json(['code'=>$addons->code,'msg'=>$addons->msg]); return json(['code'=>$addons->code,'msg'=>$addons->msg]);
} }
@ -246,6 +287,7 @@ class Addons extends AdminController
//更新失败 //更新失败
if($cpData['code'] == -1) return json(['code'=>-1,'msg'=>$cpData['msg']]); if($cpData['code'] == -1) return json(['code'=>-1,'msg'=>$cpData['msg']]);
$class = get_addons_instance($data['name']);
//添加数据库 //添加数据库
$sqlInstallFile = root_path().'addons/'.$data['name'].'/install.sql'; $sqlInstallFile = root_path().'addons/'.$data['name'].'/install.sql';
if(file_exists($sqlInstallFile)) { if(file_exists($sqlInstallFile)) {
@ -262,6 +304,8 @@ class Addons extends AdminController
$menu_arr[] = $menu['menu']; $menu_arr[] = $menu['menu'];
$this->addAddonMenu($menu_arr, (int)$pid,1); $this->addAddonMenu($menu_arr, (int)$pid,1);
} }
//执行插件安装
$class->install();
Files::delDirAndFile('../runtime/addons/'.$data['name'] . DS); Files::delDirAndFile('../runtime/addons/'.$data['name'] . DS);
@ -274,7 +318,9 @@ class Addons extends AdminController
public function uninstall() public function uninstall()
{ {
$name = input('name'); $name = input('name');
//执行插件卸载
$class = get_addons_instance($name);
$class->uninstall();
//卸载菜单 //卸载菜单
$menu = get_addons_menu($name); $menu = get_addons_menu($name);
if(!empty($menu)){ if(!empty($menu)){
@ -322,11 +368,13 @@ class Addons extends AdminController
try{ try{
$arr = ['status' => $info['status'] ? 0 :1]; $arr = ['status' => $info['status'] ? 0 :1];
set_addons_info($name,$arr); set_addons_info($name,$arr);
$class = get_addons_instance($name);
if($arr['status']) { if($arr['status']) {
$res = ['code'=>0,'msg'=>'启用成功']; $res = ['code'=>0,'msg'=>'启用成功'];
} else { } else {
$res = ['code'=>0,'msg'=>'已被禁用']; $res = ['code'=>0,'msg'=>'已被禁用'];
} }
$info['status']==1 ?$class->enabled():$class->disabled();
} catch (\Exception $e) { } catch (\Exception $e) {
throw new Exception($e->getMessage()); throw new Exception($e->getMessage());
} }
@ -339,7 +387,7 @@ class Addons extends AdminController
{ {
$name = input('name'); $name = input('name');
$config = get_addons_config($name); $config = get_addons_config($name);
if(empty($config)) return json(['code'=>-1,'msg'=>'无配置项!']); if(empty($config)) return json(['code'=>-1,'msg'=>'无配置项!无需操作']);
if(Request::isAjax()){ if(Request::isAjax()){
$params = Request::param('params/a',[],'trim'); $params = Request::param('params/a',[],'trim');
if ($params) { if ($params) {
@ -425,4 +473,16 @@ class Addons extends AdminController
} }
public function userLogin()
{
$data = Request::param();
$url = $this->getSystem()['api_url'].'/v1/user/login';
$user = Api::urlPost($url,$data);
if($user->code == 0) {
return $user;
} else {
return json(['code'=>-1,'msg'=>$user->msg]);
}
}
} }

View File

@ -182,9 +182,8 @@ class Index extends AdminController
public function cunsult() public function cunsult()
{ {
$url = $this->api.'/v1/reply'; $url = $this->api.'/v1/reply';
//$mail = Db::name('system')->where('id',1)->value('auth_mail'); // bug邮件发送
if(Request::isAjax()){ if(Request::isAjax()){
$data = Request::only(['type','title','content','post']); $data = Request::only(['type','title','content','post','uid']);
$apiRes = Api::urlPost($url,$data); $apiRes = Api::urlPost($url,$data);
$data['poster'] = Session::get('admin_id'); $data['poster'] = Session::get('admin_id');
unset($data['post']); unset($data['post']);

View File

@ -122,5 +122,15 @@ return [
'in' => 'in', 'in' => 'in',
'accumulate points' => 'Accumulate points', 'accumulate points' => 'Accumulate points',
'my post' => 'My post', 'my post' => 'My post',
'my auth' => 'My authorize' 'my auth' => 'My authorize',
'Please log in 10 minutes later' => 'Please log in 10 minutes later',
'Login error 3, Please log in 10 minutes later' => 'Login error 3, Please log in 10 minutes later',
'Account disabled' => 'Account disabled',
'Pending approval' => 'Pending approval',
'Authorized' => 'Authorized',
'Unauthorized' => 'Unauthorized',
'Free version'=> 'Free version',
'username or email' => 'Username or email',
'account or password cannot empty' => 'Account or password cannot empty'
]; ];

View File

@ -133,5 +133,7 @@ return [
'Authorized' => '已授权', 'Authorized' => '已授权',
'Unauthorized' => '未授权', 'Unauthorized' => '未授权',
'Free version'=> '免费版', 'Free version'=> '免费版',
'username or email' => '用户名或邮箱',
'account or password cannot empty' => '账号和密码不能为空'
]; ];

View File

@ -123,7 +123,17 @@ return [
'in' => '在', 'in' => '在',
'accumulate points' => '積分', 'accumulate points' => '積分',
'my post' => '我的帖子', 'my post' => '我的帖子',
'my auth' => '我的授权' 'my auth' => '我的授权',
'Please log in 10 minutes later' => '请10分钟后再登陆',
'Login error 3, Please log in 10 minutes later' => '连续登陆错误3次,请10分钟后登录',
'Account disabled' => '账号被禁用,请联系管理员',
'Pending approval' => '待审核,请联系管理员',
'Authorized' => '已授权',
'Unauthorized' => '未授权',
'Free version'=> '免费版',
'username or email' => '用户名或邮箱',
'account or password cannot empty' => '账号和密码不能为空'
]; ];

View File

@ -20,39 +20,47 @@
<script type="text/html" id="toolbar"> <script type="text/html" id="toolbar">
<div class="layui-btn-group" style="padding-bottom: 10px;"> <div class="layui-btn-group" style="padding-bottom: 10px;">
<a href="#denable" type="button" class="layui-btn layui-btn-sm" lay-event="onlineAddons">在线</a> <a href="#denable" type="button" class="layui-btn layui-btn-sm" lay-event="allAddons">全部</a>
<a href="#enable" type="button" class="layui-btn layui-btn-sm" lay-event="installed">已安装</a>
<button type="button" class="layui-btn layui-btn-sm" lay-event="freeAddons">免费</button> <button type="button" class="layui-btn layui-btn-sm" lay-event="freeAddons">免费</button>
<button type="button" class="layui-btn layui-btn-sm" lay-event="payAddons">付费</button> <button type="button" class="layui-btn layui-btn-sm" lay-event="payAddons">付费</button>
<a href="#enable" type="button" class="layui-btn layui-btn-sm" lay-event="installed">已安装</a>
</div> </div>
<div class="layui-btn-group" style="padding-bottom: 10px;"> <div class="layui-btn-group" style="padding-bottom: 10px;">
<button class="layui-btn layui-btn-sm layuiadmin-btn-admin" data-type="add">离线安装</button> <button class="layui-btn layui-btn-sm layuiadmin-btn-admin" data-type="add">离线安装</button>
<button class="layui-btn layui-btn-sm layuiadmin-btn-admin" data-type="user-info">用户信息</button>
</div> </div>
</script> </script>
<script type="text/html" id="addons-tool"> <script type="text/html" id="addons-tool">
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="install" data-url="{:url('Addons/install')}"><i class="layui-icon layui-icon-edit"></i>安装</a> {{# if(d.have_newversion === 1){ }}
<select id="vers{{d.name}}" name="sss" class="layui-border" lay-ignore lay-filter="versSelect"> <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="install" data-url="{:url('Addons/install')}"><i class="layui-icon layui-icon-edit"></i>升级</a>
{{# d.vers.forEach(function(item, index){ }} {{# } else { }}
<option value="{{ item }}">{{ item }}</option> {{# if(d.isInstall ===1) { }}
{{# }); }} <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="config" data-url="{:url('Addons/config')}"><i class="layui-icon layui-icon-set"></i>设置</a>
</select> {{# } else { }}
<a class="layui-btn layui-btn-xs" lay-event="install" data-url="{:url('Addons/install')}" data-userlogin="{:url('Addons/userLogin')}"><i class="layui-icon layui-icon-edit"></i>安装</a>
<select id="vers{{d.name}}" name="sss" class="layui-border" lay-ignore lay-filter="versSelect">
{{# d.vers.forEach(function(item, index){ }}
<option value="{{ item }}">{{ item }}</option>
{{# }); }}
</select>
{{# } }}
{{# } }}
</script> </script>
<script type="text/html" id="addons-installed-tool"> <script type="text/html" id="addons-installed-tool">
{{# if(d.status == 1){ }} {{# if(d.status == 1){ }}
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="status" data-url="{:url('Addons/status')}"><i class="layui-icon layui-icon-pause"></i>禁用</a> <a class="layui-btn layui-btn-xs" lay-event="status" data-url="{:url('Addons/status')}"><i class="layui-icon layui-icon-pause"></i>禁用</a>
{{# } else { }} {{# } else { }}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="status" data-url="{:url('Addons/status')}"><i class="layui-icon layui-icon-play"></i>启动</a> <a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="status" data-url="{:url('Addons/status')}"><i class="layui-icon layui-icon-play"></i>启动</a>
{{# } }} {{# } }}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="config" data-url="{:url('Addons/config')}"><i class="layui-icon layui-icon-set"></i>设置</a> <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="config" data-url="{:url('Addons/config')}"><i class="layui-icon layui-icon-set"></i>设置</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="uninstall" data-url="{:url('Addons/uninstall')}"><i class="layui-icon layui-icon-delete"></i>卸载</a> <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="uninstall" data-url="{:url('Addons/uninstall')}"><i class="layui-icon layui-icon-delete"></i>卸载</a>
</script> </script>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
{include file="public/user_login" /}
{/block} {/block}
{block name="js"} {block name="js"}
<script src="/static/notify.js"></script> <script src="/static/notify.js"></script>

View File

@ -336,6 +336,7 @@
</div> </div>
</div> </div>
{include file="public/user_login" /}
{/block} {/block}
{block name="js"} {block name="js"}
<script> <script>
@ -343,12 +344,29 @@
base: '/static/admin/' //静态资源所在路径 base: '/static/admin/' //静态资源所在路径
}).extend({ }).extend({
index: 'lib/index' //主入口模块 index: 'lib/index' //主入口模块
}).use(['index', 'console','element', 'layedit','form','table'],function(){ }).use(['index', 'console','element', 'layedit','form','table','notify'],function(){
var $ = layui.jquery var $ = layui.jquery
,form = layui.form ,form = layui.form
,layedit = layui.layedit ,layedit = layui.layedit
,table = layui.table ,table = layui.table
,element = layui.element; //Tab的切换功能切换事件监听等需要依赖element模块 ,element = layui.element; //Tab的切换功能切换事件监听等需要依赖element模块
var notify = layui.notify;
var api = {
userinfo: {
get: function () {
var userinfo = localStorage.getItem("taoleradmin_userinfo");
return userinfo ? JSON.parse(userinfo) : null;
},
set: function (data) {
if (data) {
localStorage.setItem("taoleradmin_userinfo", JSON.stringify(data));
} else {
localStorage.removeItem("taoleradmin_userinfo");
}
}
}
}
var index = layedit.build('L_content', { var index = layedit.build('L_content', {
height: 120 //设置编辑器高度 height: 120 //设置编辑器高度
@ -374,64 +392,99 @@
} }
}); });
// 系统调试 // 系统调试
form.on('switch(sys-sys)',function(data){ form.on('switch(sys-sys)',function(data){
var status = data.elem.checked; var status = data.elem.checked;
console.log(status);
$.post("{:url('index/sysSys')}",{status:status},function(res){ $.post("{:url('index/sysSys')}",{status:status},function(res){
if (res.code == 0) { if (res.code == 0) { notify.info(res.msg)} else {
layer.msg(res.msg,{ notify.error(res.msg);
icon:6, }
time:2000
}, function(){
location.reload();
});
} else {
layer.open({
content:res.msg,
icon:5,
anim:6
});
}
}) })
});
// 发送反馈
form.on('submit(cunsult-add)',function(data){
var field = data.field;
var userinfo = api.userinfo.get();
if(!userinfo) {
// 登录
layer.confirm('你当前还未登录TaoLer社区账号,请登录后操作!', {
title : '温馨提示',
btnAlign: 'c',
btn: ['立即登录'] //按钮
},function (index){
layer.close(index);
// 登录窗口
layer.open({
type: 1,
shadeClose: true,
title: '登录账号',
content: $("#user-info").html(),
area: ['400px','300px'],
btn: ['登录','注册'],
yes:function (index, layero) {
var url = "{:url('Addons/userLogin')}";
var data = {
name: $("#username", layero).val(),
password: $("#password", layero).val(),
};
if (!data.name || !data.password) {
notify.error('Account Or Password Cannot Empty');
return false;
}
$.ajax({
url: url, type: 'post', data: data, dataType: "json", success: function (res) {
if (res.code === 0) {
layer.close(index);
api.userinfo.set(res.data);
notify.success("登录成功", function (){
location.reload();
});
} else {
notify.alert(res.msg);
}
}, error: function (res) {
notify.error(res.msg);
}
})
},
btn2: function () {
return false;
},
success: function (layero, index) {
$(".layui-layer-btn1", layero).prop("href", "https://www.aieok.com/article/reg.html").prop("target", "_blank");
},
end: function () {
$("#login").hide();
},
});
});
} else {
field.id = userinfo.uid;
$.ajax({
type:"post",
url:"{:url('Index/cunsult')}",
data:field,
dataType:"json",
success:function (data){
if (data.code == 0) {
notify.success(data.msg, function(){location.reload()});
} else {
notify.error(res.msg);
}
}
});
}
return false;
}); });
form.on('submit(cunsult-add)',function(data){ //监听工具条
var field = data.field;
$.ajax({
type:"post",
url:"{:url('Index/cunsult')}",
data:field,
dataType:"json",
success:function (data){
if (data.code == 0) {
layer.msg(data.msg,{
icon:6,
time:2000
}, function(){
location.reload();
});
} else {
layer.open({
content:data.msg,
icon:5,
anim:6
});
}
}
});
return false;
});
//监听工具条
table.on('tool(LAY-index-topreply)', function(obj){ table.on('tool(LAY-index-topreply)', function(obj){
var data = obj.data; var data = obj.data;
if(obj.event === 'del'){ if(obj.event === 'del'){
layer.confirm('确定删除此站点?', function(index){ layer.confirm('确定删除?', function(index){
$.ajax({ $.ajax({
type:'post', type:'post',
url:"{:url('Index/delReply')}", url:"{:url('Index/delReply')}",
@ -439,24 +492,16 @@
dataType:'json', dataType:'json',
success:function(data){ success:function(data){
if(data.code == 0){ if(data.code == 0){
layer.msg(data.msg,{ notify.success(data.msg,function(){
icon:6,
time:2000
},function(){
location.reload(); location.reload();
}); });
} else { } else {
layer.open({ notify.error(res.msg);
title:'删除失败',
content:data.msg,
icon:5,
adim:6
})
} }
} }
}); });
//obj.del(); //obj.del();
table.reload('LAY-index-topreply'); table.reload('LAY-index-topreply');
layer.close(index); layer.close(index);
}); });
} }
@ -468,7 +513,16 @@
$('#up_version').html(data); $('#up_version').html(data);
}) })
})(); })();
// 用户信息清理
(function (){
var time = Date.parse(new Date());
var userinfo = api.userinfo.get();
if(userinfo) {
if(time > userinfo.expiretime *1000) {
api.userinfo.set();
}
}
})()
$('.layui-btn.layuiadmin-btn-oiltank').on('click', function(){ $('.layui-btn.layuiadmin-btn-oiltank').on('click', function(){
var type = $(this).data('type'); var type = $(this).data('type');
@ -479,8 +533,8 @@
var indexForums = "{:url('Index/forums')}", //帖子 var indexForums = "{:url('Index/forums')}", //帖子
indexReplys = "{:url('Index/replys')}", //回复 indexReplys = "{:url('Index/replys')}", //回复
indexNews = "{:url('Index/news')}", //动态 indexNews = "{:url('Index/news')}", //动态
indexReply = "{:url('Index/reply')}", //反馈 indexReply = "{:url('Index/reply')}", //反馈
monthTime = "{$monthTime}", monthTime = "{$monthTime}",
monthUserCount = "{$monthUserCount}"; monthUserCount = "{$monthUserCount}";
</script> </script>
{/block} {/block}

View File

@ -0,0 +1,27 @@
<script type="text/html" id="user-info">
<div>
<div class="layui-card">
<div class="layui-card-header" style="">
<blockquote class="layui-elem-quote" style="">温馨提示 此处账号为: <a class="font" target="_blank" href="https://www.aieok.com">TaoLer社区账号</a>
</blockquote>
</div>
<br>
<div class="layui-card-body" style="padding: 0 40px 10px 0">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label required">账号 *</label>
<div class="layui-input-block">
<input type="text" class="layui-input" lay-verify="required" id="username" value="" placeholder="{:lang('username or email')}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">密码 *</label>
<div class="layui-input-block">
<input type="password" class="layui-input" lay-verify="required" id="password" value="" placeholder="{:lang('password')}">
</div>
</div>
</form>
</div>
</div>
</div>
</script>

View File

@ -16,6 +16,7 @@ class User extends Model
protected $autoWriteTimestamp = true; //开启自动时间戳 protected $autoWriteTimestamp = true; //开启自动时间戳
protected $createTime = 'false'; protected $createTime = 'false';
protected $updateTime = 'update_time'; protected $updateTime = 'update_time';
protected $loggedUser;
//protected $auto = ['password']; //定义自动处理的字段 //protected $auto = ['password']; //定义自动处理的字段
//自动对password进行md5加密 //自动对password进行md5加密
protected function setPasswordAttr($value){ protected function setPasswordAttr($value){
@ -88,6 +89,7 @@ class User extends Model
event(new UserLogin($userInfo)); event(new UserLogin($userInfo));
//查询结果1表示有用户用户名密码正确 //查询结果1表示有用户用户名密码正确
$this->loggedUser = $user;
return 1; return 1;
} else {//密码错误登陆错误次数加1 } else {//密码错误登陆错误次数加1
$userInfo = ['type'=>'logError','id'=>$user->id]; $userInfo = ['type'=>'logError','id'=>$user->id];
@ -182,5 +184,10 @@ class User extends Model
} }
} }
// 登录用户
public function getLoggedUser(){
return $this->loggedUser;
}
} }

View File

@ -83,6 +83,7 @@ class Login extends BaseController
$user = new User(); $user = new User();
$res = $user->login($data); $res = $user->login($data);
if ($res == 1) { //登陆成功 if ($res == 1) { //登陆成功
$user = $user->getLoggedUser();
return Msgres::success('login_success',$refer); return Msgres::success('login_success',$refer);
} else { } else {
return Msgres::error($res); return Msgres::error($res);

View File

@ -35,30 +35,33 @@ class UserLogin
if($type == 'log'){ if($type == 'log'){
//$name = $user->user['name']; //$name = $user->user['name'];
$ip = request()->ip(); $ip = request()->ip();
//$url = 'http://ip-api.com/json/' . $ip . '?lang=zh-CN&fields=57361';
$url = 'http://freeapi.ipip.net/' . $ip;
$ipJson = Api::urlGetRespond($url); $url = 'http://ip-api.com/json/' . $ip . '?lang=zh-CN&fields=57361';
$respond = $ipJson->getData(); $ipJson = Api::urlGetRespond($url);
$res = $ipJson->getData();
if($respond['code'] == 0){ $data = json_decode($res['data']);
//字符串数组["中国","北京","北京"] $city ='earth';
$data = $respond['data']; if($res['code'] == 0 && !$data->status){
//正则去掉[''],保留字符串 $city = $data->city;
$str = preg_replace('/(\"|\[|\])/','',$data); }
//地址数组
$arr = explode(',', $str); //国内查询,接口已失效
if($arr[0] !== '本机地址') { // $url = 'http://freeapi.ipip.net/' . $ip;
$city = $arr[2]; // $ipJson = Api::urlGetRespond($url);
} else { // $respond = $ipJson->getData();
$city = 'earth'; // if($respond['code'] == 0){
} // //字符串数组["中国","北京","北京"]
} // $data = $respond['data'];
// if($ipJson->status == 'success'){ // //正则去掉[''],保留字符串
// $city = $ipJson->city; // $str = preg_replace('/(\"|\[|\])/','',$data);
// } else { // //地址数组
// $city ='未知'; // $arr = explode(',', $str);
// } // $city = 'earth';
// if($arr[0] !== '本机地址') {
// $city = $arr[2];
// }
// }
$u->allowField(['city','last_login_ip','last_login_time','login_error_num'])->save( $u->allowField(['city','last_login_ip','last_login_time','login_error_num'])->save(
[ [

View File

@ -16,7 +16,7 @@ return [
// 应用名,此项不可更改 // 应用名,此项不可更改
'appname' => 'TaoLer', 'appname' => 'TaoLer',
// 版本配置 // 版本配置
'version' => '2.0.3', 'version' => '2.0.4',
// 加盐 // 加盐
'salt' => 'taoler', 'salt' => 'taoler',
// 数据库备份目录 // 数据库备份目录

View File

@ -7,11 +7,11 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
upload = layui.upload; upload = layui.upload;
var notify = layui.notify; var notify = layui.notify;
function addList(type) { function getAddonsList(type,selector ) {
$.ajax({ $.ajax({
type: "post", type: "post",
url: addonsList, url: addonsList,
data: { type: type }, data: { type: type, selector: selector },
dataType: "json", dataType: "json",
success: function (res) { success: function (res) {
//渲染表格 //渲染表格
@ -19,7 +19,7 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
elem: "#addons-list", elem: "#addons-list",
toolbar: "#toolbar", toolbar: "#toolbar",
defaultToolbar: [], defaultToolbar: [],
url: addonsList + "?type=" + type, url: addonsList + "?type=" + type + "&selector=" + selector,
cols: [res["col"]], cols: [res["col"]],
page: true, page: true,
limit: 10, limit: 10,
@ -30,17 +30,39 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
}); });
} }
addList("onlineAddons"); getAddonsList("onlineAddons","all");
var api = {
userinfo: {
get: function () {
var userinfo = localStorage.getItem("taoleradmin_userinfo");
return userinfo ? JSON.parse(userinfo) : null;
},
set: function (data) {
if (data) {
localStorage.setItem("taoleradmin_userinfo", JSON.stringify(data));
} else {
localStorage.removeItem("taoleradmin_userinfo");
}
}
}
}
//头工具栏事件 //头工具栏事件
table.on("toolbar(addons-list)", function (obj) { table.on("toolbar(addons-list)", function (obj) {
var checkStatus = table.checkStatus(obj.config.id); var checkStatus = table.checkStatus(obj.config.id);
switch (obj.event) { switch (obj.event) {
case "installed": case "installed":
addList("installed"); getAddonsList("installed",'');
break; break;
case "onlineAddons": case "allAddons":
addList("onlineAddons"); getAddonsList("onlineAddons","all");
break;
case "freeAddons":
getAddonsList("onlineAddons","free");
break;
case "payAddons":
getAddonsList("onlineAddons","pay");
break; break;
} }
}); });
@ -53,15 +75,78 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
//安装插件 //安装插件
if (event === "install") { if (event === "install") {
var index = layer.load(1); // 检测权限
$.post(url, { name: data.name, version: data.version }, function (res) { var userinfo = api.userinfo.get();
if (res.code == 0) { var userLoginUrl = $(this).data('userlogin');
notify.success(res.msg, "topRight"); if(userinfo) {
} else { notify.confirm("确认安装吗?", "vcenter",function(){
notify.error(res.msg, "topRight"); var index = layer.load(1);
} $.post(url, { name: data.name, version: data.version, uid: userinfo.uid, token: userinfo.token }, function (res) {
if (res.code == 0) {
notify.success(res.msg, "topRight");
} else {
notify.error(res.msg, "topRight");
}
layer.close(index);
});
});
} else {
// 登录
layer.confirm('你当前还未登录TaoLer社区账号,请登录后操作!', {
title : '温馨提示',
btnAlign: 'c',
btn: ['立即登录'] //按钮
},function (index){
layer.close(index); layer.close(index);
}); // 登录窗口
layer.open({
type: 1,
shadeClose: true,
title: '登录账号',
content: $("#user-info").html(),
area: ['400px','300px'],
btn: ['登录','注册'],
yes:function (index, layero) {
var url = userLoginUrl;
var data = {
name: $("#username", layero).val(),
password: $("#password", layero).val(),
};
if (!data.name || !data.password) {
notify.error('Account Or Password Cannot Empty');
return false;
}
$.ajax({
url: url, type: 'post', data: data, dataType: "json", success: function (res) {
if (res.code === 0) {
layer.close(index);
api.userinfo.set(res.data);
notify.success("登录成功", function (){
location.reload();
});
} else {
notify.alert(res.msg);
}
}, error: function (res) {
notify.error(res.msg);
}
})
},
btn2: function () {
return false;
},
success: function (layero, index) {
$(".layui-layer-btn1", layero).prop("href", "https://www.aieok.com/article/reg.html").prop("target", "_blank");
},
end: function () {
$("#login").hide();
},
});
});
}
} }
// 启用禁用 // 启用禁用
@ -74,12 +159,8 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
notify.error(res.msg, "topRight"); notify.error(res.msg, "topRight");
} }
table.reloadData("addons-list",{},'deep'); table.reloadData("addons-list",{},'deep');
// addList("installed");
}); });
}); });
} }
// 卸载插件 // 卸载插件
@ -100,67 +181,74 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
// 配置插件 // 配置插件
if (event === "config") { if (event === "config") {
layer.open({ $.post(url,{name:data.name},function (res){
type: 2, // 无配置项拦截
title: '配置插件', if (res.code == -1) {
content: url + "?name=" + data.name, notify.alert(res.msg);
maxmin: true, return false;
area: ["780px", "90%"], }
btn: ["确定", "取消"], layer.open({
yes: function (index, layero) { type: 2,
var iframeWindow = window["layui-layer-iframe" + index], title: '配置插件',
submitID = "LAY-addons-config-submit", content: url + "?name=" + data.name,
submit = layero.find("iframe").contents().find("#" + submitID); maxmin: true,
//监听提交 area: ["780px", "90%"],
iframeWindow.layui.form.on( btn: ["确定", "取消"],
"submit(" + submitID + ")", yes: function (index, layero) {
function (data) { var iframeWindow = window["layui-layer-iframe" + index],
var field = data.field; //获取提交的字段 submitID = "LAY-addons-config-submit",
$.ajax({ submit = layero.find("iframe").contents().find("#" + submitID);
type: "post", //监听提交
url: url, iframeWindow.layui.form.on("submit(" + submitID + ")",
data: field, function (data) {
daType: "json", var field = data.field; //获取提交的字段
success: function (res) { $.ajax({
if (res.code == 0) { type: "post",
notify.success(res.msg, "topRight"); url: url,
} else { data: field,
notify.error(res.msg, "topRight"); daType: "json",
} success: function (res) {
}, if (res.code == 0) {
}); notify.success(res.msg, "topRight");
layer.close(index); //关闭弹层 } else {
} notify.error(res.msg, "topRight");
); }
submit.trigger("click"); },
}, });
success: function (layero, index) { layer.close(index); //关闭弹层
var forms = layero.find("iframe").contents().find(".layui-form"); }
var button = forms.find("button"); );
//事件委托 submit.trigger("click");
forms.on("click", "button", function (data) { },
var even = this.getAttribute("lay-event"); success: function (layero, index) {
var names = this.dataset.name; var forms = layero.find("iframe").contents().find(".layui-form");
// if (even == "addInput") { var button = forms.find("button");
// var html = '<div class="layui-form-item">\n' + //事件委托
// '<label class="layui-form-label"></label>\n' + forms.on("click", "button", function (data) {
// '<div class="layui-input-inline">\n' + var even = this.getAttribute("lay-event");
// ' <input type="text" name="'+ names +'[key][]" value="" placeholder="key" autocomplete="off" class="layui-input input-double-width">\n' + var names = this.dataset.name;
// '</div>\n' + // if (even == "addInput") {
// '<div class="layui-input-inline">\n' + // var html = '<div class="layui-form-item">\n' +
// ' <input type="text" name="'+ names +'[value][]" value="" placeholder="value" autocomplete="off" class="layui-input input-double-width">\n' + // '<label class="layui-form-label"></label>\n' +
// '</div>\n' + // '<div class="layui-input-inline">\n' +
// '<button data-name="'+ names +'" type="button" class="layui-btn layui-btn-danger layui-btn-sm removeInupt" lay-event="removeInupt">\n' + // ' <input type="text" name="'+ names +'[key][]" value="" placeholder="key" autocomplete="off" class="layui-input input-double-width">\n' +
// ' <i class="layui-icon"></i>\n' + // '</div>\n' +
// '</button>\n' + // '<div class="layui-input-inline">\n' +
// '</div>'; // ' <input type="text" name="'+ names +'[value][]" value="" placeholder="value" autocomplete="off" class="layui-input input-double-width">\n' +
// $(this).parent().parent().append(html); // '</div>\n' +
// } else { // '<button data-name="'+ names +'" type="button" class="layui-btn layui-btn-danger layui-btn-sm removeInupt" lay-event="removeInupt">\n' +
// $(this).parent().remove(); // ' <i class="layui-icon"></i>\n' +
// } // '</button>\n' +
}); // '</div>';
}, // $(this).parent().parent().append(html);
// } else {
// $(this).parent().remove();
// }
});
},
});
}); });
} }
if (event === "edit") { if (event === "edit") {

View File

@ -284,3 +284,40 @@ if (!function_exists('get_addons_menu')) {
} }
} }
if (!function_exists('get_addons_list')) {
/**
* 获得插件列表
* @return array
*/
function get_addons_list()
{
$list = Cache::get('addonslist');
if (empty($list)) {
$addonsPath = app()->getRootPath().'addons'.DS; // 插件列表
$results = scandir($addonsPath);
$list = [];
foreach ($results as $name) {
if ($name === '.' or $name === '..')
continue;
if (is_file($addonsPath . $name))
continue;
$addonDir = $addonsPath . $name . DS;
if (!is_dir($addonDir))
continue;
if (!is_file($addonDir . 'Plugin' . '.php'))
continue;
$info = get_addons_info($name);
if (!isset($info['name']))
continue;
$info['url'] =isset($info['url']) && $info['url'] ?(string)addons_url($info['url']):'';
$list[$name] = $info;
}
Cache::set('addonslist', $list);
}
return $list;
}
}