diff --git a/app/admin/controller/Addons.php b/app/admin/controller/Addons.php
index 18aed6f..4249af2 100644
--- a/app/admin/controller/Addons.php
+++ b/app/admin/controller/Addons.php
@@ -31,17 +31,19 @@ class Addons extends AdminController
*/
public function addonsList()
{
-
- $type = input('type');
- $data = Request::only(['page', 'limit']);
- $res = [];
- switch($type){
+ $data = Request::param();
+ $res = [];
+ //本地插件列表
+ $addonsList = Files::getDirName('../addons/');
+ $url = $this->getSystem()['api_url'].'/v1/addons';
+ $addons = Api::urlGet($url);
+
+ switch($data['type']){
//已安装
case 'installed':
- $addons = Files::getDirName('../addons/');
- if($addons){
+ if($addonsList){
$res = ['code'=>0,'msg'=>'','count'=>5];
- foreach($addons as $v){
+ foreach($addonsList as $v){
$info_file = '../addons/'.$v.'/info.ini';
$info = parse_ini_file($info_file);
$info['show'] = $info['status'] ? '启用' : '禁用';
@@ -52,7 +54,7 @@ class Addons extends AdminController
['type' => 'numbers'],
['field' => 'name','title'=> '插件', 'width'=> 120],
['field'=> 'title','title'=> '标题', 'width'=> 100],
- ['field'=> 'version','title'=> '版本', 'width'=> 60],
+ ['field'=> 'version','title'=> '版本', 'templet' => '
{{d.version}}
', 'width'=> 60],
['field' => 'author','title'=> '作者', 'width'=> 80],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'show','title'=> '状态', 'width'=> 100],
@@ -64,14 +66,54 @@ class Addons extends AdminController
$res = ['code'=>-1,'msg'=>'没有安装任何插件'];
}
break;
- //在线
+ //在线全部
case 'onlineAddons':
- $url = $this->getSystem()['api_url'].'/v1/addons';
- $addons = Api::urlGet($url);
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['msg'] = '';
- $res['data'] = $addons->data;
$res['col'] = [
['type' => 'numbers'],
['field' => 'title','title'=> '插件', 'width'=> 200],
@@ -79,14 +121,13 @@ class Addons extends AdminController
['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'price','title'=> '价格(元)','width'=> 80],
['field' => 'downloads','title'=> '下载', 'width'=> 70],
- ['field' => 'version','title'=> '版本', 'width'=> 70],
+ ['field' => 'version','title'=> '版本', 'templet' => '{{d.version}} {{# if(d.have_newversion == 1){ }}{{# } }}
','width'=> 70],
['field' => 'status','title'=> '状态', 'width'=> 70],
['title' => '操作', 'width'=> 150, 'align'=>'center', 'toolbar'=> '#addons-tool']
];
} else {
$res = ['code'=>-1,'msg'=>'未获取到服务器信息'];
}
-
break;
}
return json($res);
@@ -181,10 +222,10 @@ class Addons extends AdminController
//安装插件
public function install()
{
- $data = Request::param();
-
+ $data = Request::param();
$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) {
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']]);
+ $class = get_addons_instance($data['name']);
//添加数据库
$sqlInstallFile = root_path().'addons/'.$data['name'].'/install.sql';
if(file_exists($sqlInstallFile)) {
@@ -262,6 +304,8 @@ class Addons extends AdminController
$menu_arr[] = $menu['menu'];
$this->addAddonMenu($menu_arr, (int)$pid,1);
}
+ //执行插件安装
+ $class->install();
Files::delDirAndFile('../runtime/addons/'.$data['name'] . DS);
@@ -274,7 +318,9 @@ class Addons extends AdminController
public function uninstall()
{
$name = input('name');
-
+ //执行插件卸载
+ $class = get_addons_instance($name);
+ $class->uninstall();
//卸载菜单
$menu = get_addons_menu($name);
if(!empty($menu)){
@@ -322,11 +368,13 @@ class Addons extends AdminController
try{
$arr = ['status' => $info['status'] ? 0 :1];
set_addons_info($name,$arr);
+ $class = get_addons_instance($name);
if($arr['status']) {
$res = ['code'=>0,'msg'=>'启用成功'];
} else {
$res = ['code'=>0,'msg'=>'已被禁用'];
}
+ $info['status']==1 ?$class->enabled():$class->disabled();
} catch (\Exception $e) {
throw new Exception($e->getMessage());
}
@@ -339,7 +387,7 @@ class Addons extends AdminController
{
$name = input('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()){
$params = Request::param('params/a',[],'trim');
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]);
+ }
+ }
+
}
diff --git a/app/admin/controller/Index.php b/app/admin/controller/Index.php
index 122c064..3b1fabc 100644
--- a/app/admin/controller/Index.php
+++ b/app/admin/controller/Index.php
@@ -182,9 +182,8 @@ class Index extends AdminController
public function cunsult()
{
$url = $this->api.'/v1/reply';
- //$mail = Db::name('system')->where('id',1)->value('auth_mail'); // bug邮件发送
if(Request::isAjax()){
- $data = Request::only(['type','title','content','post']);
+ $data = Request::only(['type','title','content','post','uid']);
$apiRes = Api::urlPost($url,$data);
$data['poster'] = Session::get('admin_id');
unset($data['post']);
diff --git a/app/admin/lang/en-us.php b/app/admin/lang/en-us.php
index dfce03f..7cd5665 100644
--- a/app/admin/lang/en-us.php
+++ b/app/admin/lang/en-us.php
@@ -122,5 +122,15 @@ return [
'in' => 'in',
'accumulate points' => 'Accumulate points',
'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'
];
\ No newline at end of file
diff --git a/app/admin/lang/zh-cn.php b/app/admin/lang/zh-cn.php
index bcda12f..a8b4388 100644
--- a/app/admin/lang/zh-cn.php
+++ b/app/admin/lang/zh-cn.php
@@ -133,5 +133,7 @@ return [
'Authorized' => '已授权',
'Unauthorized' => '未授权',
'Free version'=> '免费版',
+ 'username or email' => '用户名或邮箱',
+ 'account or password cannot empty' => '账号和密码不能为空'
];
\ No newline at end of file
diff --git a/app/admin/lang/zh-tw.php b/app/admin/lang/zh-tw.php
index 47ff9cf..376b22f 100644
--- a/app/admin/lang/zh-tw.php
+++ b/app/admin/lang/zh-tw.php
@@ -123,7 +123,17 @@ return [
'in' => '在',
'accumulate points' => '積分',
'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' => '账号和密码不能为空'
];
\ No newline at end of file
diff --git a/app/admin/view/addons/index.html b/app/admin/view/addons/index.html
index 6656959..aca6a32 100644
--- a/app/admin/view/addons/index.html
+++ b/app/admin/view/addons/index.html
@@ -20,39 +20,47 @@
+
-
+{include file="public/user_login" /}
{/block}
{block name="js"}
diff --git a/app/admin/view/index/home.html b/app/admin/view/index/home.html
index 61db1ee..611187e 100644
--- a/app/admin/view/index/home.html
+++ b/app/admin/view/index/home.html
@@ -336,6 +336,7 @@
+{include file="public/user_login" /}
{/block}
{block name="js"}
{/block}
\ No newline at end of file
diff --git a/app/admin/view/public/user_login.html b/app/admin/view/public/user_login.html
new file mode 100644
index 0000000..263fd8f
--- /dev/null
+++ b/app/admin/view/public/user_login.html
@@ -0,0 +1,27 @@
+
\ No newline at end of file
diff --git a/app/common/model/User.php b/app/common/model/User.php
index ffe09c6..049e9fd 100644
--- a/app/common/model/User.php
+++ b/app/common/model/User.php
@@ -16,6 +16,7 @@ class User extends Model
protected $autoWriteTimestamp = true; //开启自动时间戳
protected $createTime = 'false';
protected $updateTime = 'update_time';
+ protected $loggedUser;
//protected $auto = ['password']; //定义自动处理的字段
//自动对password进行md5加密
protected function setPasswordAttr($value){
@@ -88,6 +89,7 @@ class User extends Model
event(new UserLogin($userInfo));
//查询结果1表示有用户,用户名密码正确
+ $this->loggedUser = $user;
return 1;
} else {//密码错误登陆错误次数加1
$userInfo = ['type'=>'logError','id'=>$user->id];
@@ -181,6 +183,11 @@ class User extends Model
return '修改失败,请改换密码';
}
}
+
+ // 登录用户
+ public function getLoggedUser(){
+ return $this->loggedUser;
+ }
}
\ No newline at end of file
diff --git a/app/index/controller/Login.php b/app/index/controller/Login.php
index 6aefce3..0b2daa1 100644
--- a/app/index/controller/Login.php
+++ b/app/index/controller/Login.php
@@ -83,6 +83,7 @@ class Login extends BaseController
$user = new User();
$res = $user->login($data);
if ($res == 1) { //登陆成功
+ $user = $user->getLoggedUser();
return Msgres::success('login_success',$refer);
} else {
return Msgres::error($res);
diff --git a/app/listener/UserLogin.php b/app/listener/UserLogin.php
index 40ae0b3..2a6a740 100644
--- a/app/listener/UserLogin.php
+++ b/app/listener/UserLogin.php
@@ -35,30 +35,33 @@ class UserLogin
if($type == 'log'){
//$name = $user->user['name'];
$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);
- $respond = $ipJson->getData();
-
- if($respond['code'] == 0){
- //字符串数组["中国","北京","北京"]
- $data = $respond['data'];
- //正则去掉[''],保留字符串
- $str = preg_replace('/(\"|\[|\])/','',$data);
- //地址数组
- $arr = explode(',', $str);
- if($arr[0] !== '本机地址') {
- $city = $arr[2];
- } else {
- $city = 'earth';
- }
- }
- // if($ipJson->status == 'success'){
- // $city = $ipJson->city;
- // } else {
- // $city ='未知';
- // }
+
+ $url = 'http://ip-api.com/json/' . $ip . '?lang=zh-CN&fields=57361';
+ $ipJson = Api::urlGetRespond($url);
+ $res = $ipJson->getData();
+
+ $data = json_decode($res['data']);
+ $city ='earth';
+ if($res['code'] == 0 && !$data->status){
+ $city = $data->city;
+ }
+
+ //国内查询,接口已失效
+// $url = 'http://freeapi.ipip.net/' . $ip;
+// $ipJson = Api::urlGetRespond($url);
+// $respond = $ipJson->getData();
+// if($respond['code'] == 0){
+// //字符串数组["中国","北京","北京"]
+// $data = $respond['data'];
+// //正则去掉[''],保留字符串
+// $str = preg_replace('/(\"|\[|\])/','',$data);
+// //地址数组
+// $arr = explode(',', $str);
+// $city = 'earth';
+// if($arr[0] !== '本机地址') {
+// $city = $arr[2];
+// }
+// }
$u->allowField(['city','last_login_ip','last_login_time','login_error_num'])->save(
[
diff --git a/config/taoler.php b/config/taoler.php
index e9a3648..17c9df7 100644
--- a/config/taoler.php
+++ b/config/taoler.php
@@ -16,7 +16,7 @@ return [
// 应用名,此项不可更改
'appname' => 'TaoLer',
// 版本配置
- 'version' => '2.0.3',
+ 'version' => '2.0.4',
// 加盐
'salt' => 'taoler',
// 数据库备份目录
diff --git a/public/static/admin/modules/addons.js b/public/static/admin/modules/addons.js
index 68096cf..32da7e7 100644
--- a/public/static/admin/modules/addons.js
+++ b/public/static/admin/modules/addons.js
@@ -7,11 +7,11 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
upload = layui.upload;
var notify = layui.notify;
- function addList(type) {
+ function getAddonsList(type,selector ) {
$.ajax({
type: "post",
url: addonsList,
- data: { type: type },
+ data: { type: type, selector: selector },
dataType: "json",
success: function (res) {
//渲染表格
@@ -19,7 +19,7 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
elem: "#addons-list",
toolbar: "#toolbar",
defaultToolbar: [],
- url: addonsList + "?type=" + type,
+ url: addonsList + "?type=" + type + "&selector=" + selector,
cols: [res["col"]],
page: true,
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) {
var checkStatus = table.checkStatus(obj.config.id);
switch (obj.event) {
case "installed":
- addList("installed");
+ getAddonsList("installed",'');
break;
- case "onlineAddons":
- addList("onlineAddons");
+ case "allAddons":
+ getAddonsList("onlineAddons","all");
+ break;
+ case "freeAddons":
+ getAddonsList("onlineAddons","free");
+ break;
+ case "payAddons":
+ getAddonsList("onlineAddons","pay");
break;
}
});
@@ -53,15 +75,78 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
//安装插件
if (event === "install") {
- var index = layer.load(1);
- $.post(url, { name: data.name, version: data.version }, function (res) {
- if (res.code == 0) {
- notify.success(res.msg, "topRight");
- } else {
- notify.error(res.msg, "topRight");
- }
+ // 检测权限
+ var userinfo = api.userinfo.get();
+ var userLoginUrl = $(this).data('userlogin');
+ if(userinfo) {
+ notify.confirm("确认安装吗?", "vcenter",function(){
+ 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.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");
}
table.reloadData("addons-list",{},'deep');
- // addList("installed");
});
-
});
-
-
}
// 卸载插件
@@ -100,67 +181,74 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
// 配置插件
if (event === "config") {
- layer.open({
- type: 2,
- title: '配置插件',
- content: url + "?name=" + data.name,
- maxmin: true,
- area: ["780px", "90%"],
- btn: ["确定", "取消"],
- yes: function (index, layero) {
- var iframeWindow = window["layui-layer-iframe" + index],
- submitID = "LAY-addons-config-submit",
- submit = layero.find("iframe").contents().find("#" + submitID);
- //监听提交
- iframeWindow.layui.form.on(
- "submit(" + submitID + ")",
- function (data) {
- var field = data.field; //获取提交的字段
- $.ajax({
- type: "post",
- url: url,
- data: field,
- daType: "json",
- success: function (res) {
- if (res.code == 0) {
- notify.success(res.msg, "topRight");
- } else {
- notify.error(res.msg, "topRight");
- }
- },
- });
- layer.close(index); //关闭弹层
- }
- );
- submit.trigger("click");
- },
- success: function (layero, index) {
- var forms = layero.find("iframe").contents().find(".layui-form");
- var button = forms.find("button");
- //事件委托
- forms.on("click", "button", function (data) {
- var even = this.getAttribute("lay-event");
- var names = this.dataset.name;
- // if (even == "addInput") {
- // var html = '';
- // $(this).parent().parent().append(html);
- // } else {
- // $(this).parent().remove();
- // }
- });
- },
+ $.post(url,{name:data.name},function (res){
+ // 无配置项拦截
+ if (res.code == -1) {
+ notify.alert(res.msg);
+ return false;
+ }
+ layer.open({
+ type: 2,
+ title: '配置插件',
+ content: url + "?name=" + data.name,
+ maxmin: true,
+ area: ["780px", "90%"],
+ btn: ["确定", "取消"],
+ yes: function (index, layero) {
+ var iframeWindow = window["layui-layer-iframe" + index],
+ submitID = "LAY-addons-config-submit",
+ submit = layero.find("iframe").contents().find("#" + submitID);
+ //监听提交
+ iframeWindow.layui.form.on("submit(" + submitID + ")",
+ function (data) {
+ var field = data.field; //获取提交的字段
+ $.ajax({
+ type: "post",
+ url: url,
+ data: field,
+ daType: "json",
+ success: function (res) {
+ if (res.code == 0) {
+ notify.success(res.msg, "topRight");
+ } else {
+ notify.error(res.msg, "topRight");
+ }
+ },
+ });
+ layer.close(index); //关闭弹层
+ }
+ );
+ submit.trigger("click");
+ },
+ success: function (layero, index) {
+ var forms = layero.find("iframe").contents().find(".layui-form");
+ var button = forms.find("button");
+ //事件委托
+ forms.on("click", "button", function (data) {
+ var even = this.getAttribute("lay-event");
+ var names = this.dataset.name;
+ // if (even == "addInput") {
+ // var html = '';
+ // $(this).parent().parent().append(html);
+ // } else {
+ // $(this).parent().remove();
+ // }
+ });
+ },
+ });
});
+
}
if (event === "edit") {
diff --git a/vendor/taoser/think-addons/src/helper.php b/vendor/taoser/think-addons/src/helper.php
index b726ddc..b84612b 100644
--- a/vendor/taoser/think-addons/src/helper.php
+++ b/vendor/taoser/think-addons/src/helper.php
@@ -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;
+ }
+
+
+
+}
+