From 26a35c9738f23ad175eb09c9355790c240492496 Mon Sep 17 00:00:00 2001 From: Karson <karsonzhang@163.com> Date: Sun, 4 Feb 2018 00:36:17 +0800 Subject: [PATCH] 新增插件在线一键升级功能 新增安装指定插件版本 修复二级管理员无法添加管理员的BUG 优化require-table在add_url的ids替换 --- application/admin/controller/Addon.php | 53 +++++++++++++++++++++++++++++++++++++++++++++++++---- application/admin/controller/auth/Admin.php | 26 +++++++++++++++++--------- application/admin/lang/zh-cn/addon.php | 3 +++ application/admin/view/addon/index.html | 50 ++++++++++++++++++++++++++++++++++++++++++++------ application/config.php | 2 +- public/assets/js/backend/addon.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- public/assets/js/require-backend.min.js | 4 +++- public/assets/js/require-table.js | 4 +++- 8 files changed, 168 insertions(+), 26 deletions(-) diff --git a/application/admin/controller/Addon.php b/application/admin/controller/Addon.php index 4abe86f..7f914c6 100644 --- a/application/admin/controller/Addon.php +++ b/application/admin/controller/Addon.php @@ -62,7 +62,6 @@ class Addon extends Backend $params = $this->request->post("row/a"); if ($params) { - $configList = []; foreach ($config as $k => &$v) { if (isset($params[$v['name']])) @@ -124,9 +123,18 @@ class Addon extends Backend { $uid = $this->request->post("uid"); $token = $this->request->post("token"); - Service::install($name, $force, ['uid' => $uid, 'token' => $token]); + $version = $this->request->post("version"); + $faversion = $this->request->post("faversion"); + $extend = [ + 'uid' => $uid, + 'token' => $token, + 'version' => $version, + 'faversion' => $faversion + ]; + Service::install($name, $force, $extend); $info = get_addon_info($name); $info['config'] = get_addon_config($name) ? 1 : 0; + $info['state'] = 1; $this->success(__('Install successful'), null, ['addon' => $info]); } catch (AddonException $e) @@ -283,6 +291,42 @@ class Addon extends Backend } /** + * 更新插件 + */ + public function upgrade() + { + $name = $this->request->post("name"); + if (!$name) + { + $this->error(__('Parameter %s can not be empty', 'name')); + } + try + { + $uid = $this->request->post("uid"); + $token = $this->request->post("token"); + $version = $this->request->post("version"); + $faversion = $this->request->post("faversion"); + $extend = [ + 'uid' => $uid, + 'token' => $token, + 'version' => $version, + 'faversion' => $faversion + ]; + //调用更新的方法 + Service::upgrade($name, $extend); + $this->success(__('Operate successful')); + } + catch (AddonException $e) + { + $this->result($e->getData(), $e->getCode(), $e->getMessage()); + } + catch (Exception $e) + { + $this->error($e->getMessage()); + } + } + + /** * 刷新缓存 */ public function refresh() @@ -314,14 +358,15 @@ class Addon extends Backend { if ($search && stripos($v['name'], $search) === FALSE && stripos($v['intro'], $search) === FALSE) continue; + $v['flag'] = ''; $v['banner'] = ''; $v['image'] = ''; $v['donateimage'] = ''; $v['demourl'] = ''; $v['price'] = '0.00'; - $v['url'] = '/addons/' . $v['name']; - $v['createtime'] = 0; + $v['url'] = addon_url($v['name']); + $v['createtime'] = filemtime(ADDON_PATH . $v['name']); $list[] = $v; } $total = count($list); diff --git a/application/admin/controller/auth/Admin.php b/application/admin/controller/auth/Admin.php index 4c7431e..c3747b5 100644 --- a/application/admin/controller/auth/Admin.php +++ b/application/admin/controller/auth/Admin.php @@ -27,30 +27,38 @@ class Admin extends Backend $this->model = model('Admin'); $this->childrenAdminIds = $this->auth->getChildrenAdminIds(true); - $this->childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin() ? true : false); + $this->childrenGroupIds = $this->auth->getChildrenGroupIds(true); $groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray(); + Tree::instance()->init($groupList); - $result = []; + $groupdata = []; if ($this->auth->isSuperAdmin()) { $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); + foreach ($result as $k => $v) + { + $groupdata[$v['id']] = $v['name']; + } } else { + $result = []; $groups = $this->auth->getGroups(); foreach ($groups as $m => $n) { - $result = array_merge($result, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid']))); + $childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id'])); + $temp = []; + foreach ($childlist as $k => $v) + { + $temp[$v['id']] = $v['name']; + } + $result[__($n['name'])] = $temp; } - } - $groupName = []; - foreach ($result as $k => $v) - { - $groupName[$v['id']] = $v['name']; + $groupdata = $result; } - $this->view->assign('groupdata', $groupName); + $this->view->assign('groupdata', $groupdata); $this->assignconfig("admin", ['id' => $this->auth->id]); } diff --git a/application/admin/lang/zh-cn/addon.php b/application/admin/lang/zh-cn/addon.php index 250f7a0..3fb633b 100644 --- a/application/admin/lang/zh-cn/addon.php +++ b/application/admin/lang/zh-cn/addon.php @@ -22,11 +22,13 @@ return [ 'Pay click tips' => '请点击这里在新窗口中进行支付!', 'Pay new window tips' => '请在新弹出的窗口中进行支付,支付完成后再重新点击安装按钮进行安装!', 'Uninstall tips' => '确认卸载插件?<p class="text-danger">卸载将会删除所有插件文件且不可找回!!! 插件如果有创建数据库表请手动删除!!!</p>如有重要数据请备份后再操作!', + 'Upgrade tips' => '确认升级插件?<p class="text-danger">如果之前购买插件时未登录,此次升级可能出现购买后才可以下载的提示!!!<br>升级后可能出现部分冗余数据记录,请根据需要移除即可!!!</p>如有重要数据请备份后再操作!', 'Offline installed tips' => '插件安装成功!你需要手动启用该插件,并清除缓存使之生效', 'Online installed tips' => '插件安装成功!清除插件缓存和框架缓存后生效!', 'Not login tips' => '你当前未登录FastAdmin,登录后将同步已购买的记录,下载时无需二次付费!', 'Not installed tips' => '请安装后再访问插件前台页面!', 'Not enabled tips' => '插件已经禁用,请启用后再访问插件前台页面!', + 'Please disable addon first' => '请先禁用插件再进行升级', 'Login now' => '立即登录', 'Continue install' => '不登录,继续安装', 'Recommend' => '推荐', @@ -49,6 +51,7 @@ return [ 'Feedback' => '反馈BUG', 'Install' => '安装', 'Uninstall' => '卸载', + 'Upgrade' => '升级', 'Setting' => '配置', 'Disable' => '禁用', 'Enable' => '启用', diff --git a/application/admin/view/addon/index.html b/application/admin/view/addon/index.html index 5cbea77..ba6aae2 100644 --- a/application/admin/view/addon/index.html +++ b/application/admin/view/addon/index.html @@ -2,7 +2,8 @@ .noimage {width:100%;text-align: center;background:#18bc9c;color:#fff;padding-bottom:66.66%;position:relative;} .noimage > div {position: absolute;top:48%;width:100%;text-align:center;} .addon {position: relative;} - .addon > span {position:absolute;left:15px;top:15px;} + .addon > span {position:absolute;left:15px;top:15px;z-index:9;} + .addon > span a{opacity: 0.5;border:none;color:#fff;} .layui-layer-pay .layui-layer-content {padding:0;height:600px!important;} .layui-layer-pay {border:none;} .payimg{position:relative;width:800px;height:600px;} @@ -162,8 +163,14 @@ <% var label = labelarr[item.id % 5]; %> <% var addon = typeof addons[item.name]!= 'undefined' ? addons[item.name] : null; %> <div class="thumbnail addon"> - <!--<span class="btn btn-primary"><%=item.name%></span>--> - <a href="<%=addon?addon.url:'javascript:;'%>" class="btn-addonindex" target="_blank"> + <%if(addon){%> + <span> + <a href="<%=addon.url%>" target="_blank" class="btn btn-xs"> + <i class="fa fa-home"></i> + </a> + </span> + <%}%> + <a href="<%=item.url%>" class="btn-addonindex" target="_blank"> <%if(item.image){%> <img src="<%=item.image%>" class="img-responsive" alt="<%=item.title%>"> <%}else{%> @@ -190,9 +197,23 @@ <p class="text-muted">{:__('Intro')}: <%=item.intro%></p> <p class="text-muted">{:__('Version')}: <%=# addon && item && addon.version!=item.version?'<span class="label label-danger">'+addon.version+'</span> -> <span class="label label-success">'+item.version+'</span>':item.version%></p> <p class="text-muted">{:__('Createtime')}: <%=Moment(item.createtime*1000).format("YYYY-MM-DD HH:mm:ss")%></p> - <p class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>"> + <div class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>"> <% if(!addon){ %> - <a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a> + <% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%> + <span class="btn-group"> + <a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>" data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a> + <a class="btn btn-success dropdown-toggle" data-toggle="dropdown" href="javascript:;"> + <span class="fa fa-caret-down"></span> + </a> + <ul class="dropdown-menu"> + <% for(var i=0;i< item.releaselist.length;i++){ %> + <li><a href="javascript:;" class="btn-install" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>" data-version="<%=item.releaselist[i].version%>"><%=item.releaselist[i].version%></a></li> + <% } %> + </ul> + </span> + <% }else{%> + <a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>" data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a> + <% } %> <% if(item.demourl){ %> <a href="<%=item.demourl%>" class="btn btn-primary btn-info btn-demo" target="_blank"><i class="fa fa-flash"></i> {:__('Demo')}</a> <% } %> @@ -209,12 +230,29 @@ <a href="javascript:;" class="btn btn-danger btn-uninstall"><i class="fa fa-times"></i> {:__('Uninstall')}</a> <% } %> <% } %> + <% if(addon && item && addon.version!=item.version){%> + <% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%> + <span class="btn-group"> + <a href="javascript:;" class="btn btn-info btn-success btn-upgrade" data-version="<%=item.version%>"><i class="fa fa-cloud"></i> {:__('Upgrade')}</a> + <a class="btn btn-info dropdown-toggle" data-toggle="dropdown" href="javascript:;"> + <span class="fa fa-caret-down"></span> + </a> + <ul class="dropdown-menu"> + <% for(var i=0;i< item.releaselist.length;i++){ %> + <li><a href="javascript:;" class="btn-upgrade" data-version="<%=item.releaselist[i].version%>"><%=item.releaselist[i].version%></a></li> + <% } %> + </ul> + </span> + <% }else{%> + <a href="javascript:;" class="btn btn-info btn-upgrade" data-version="<%=item.version%>"><i class="fa fa-cloud"></i> {:__('Upgrade')}</a> + <% }%> + <% }%> <span class="pull-right" style="margin-top:10px;"> <a href="javascript:;" class="btn-addoninfo text-gray" data-index="<%=i%>" title="<%=item.title?item.title:'{:__('None')}'%>"><i class="fa fa-bars"></i></a> </span> - </p> + </div> </div> </div> </div> diff --git a/application/config.php b/application/config.php index 213531a..96299e9 100755 --- a/application/config.php +++ b/application/config.php @@ -253,7 +253,7 @@ return [ //自动检测更新 'checkupdate' => false, //版本号 - 'version' => '1.0.0.20180130_beta', + 'version' => '1.0.0.20180204_beta', 'api_url' => 'http://api.fastadmin.net', ], ]; diff --git a/public/assets/js/backend/addon.js b/public/assets/js/backend/addon.js index b499904..631aeab 100644 --- a/public/assets/js/backend/addon.js +++ b/public/assets/js/backend/addon.js @@ -22,8 +22,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function if (e.keyCode == 13) { var that = this; var options = table.bootstrapTable('getOptions'); + var queryParams = options.queryParams; options.pageNumber = 1; options.queryParams = function (params) { + var params = queryParams(params); params.search = $(that).val(); return params; }; @@ -53,7 +55,16 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function showExport: false, commonSearch: false, searchFormVisible: false, - pageSize: 12 + pageSize: 12, + queryParams: function (params) { + var filter = params.filter ? JSON.parse(params.filter) : {}; + var op = params.op ? JSON.parse(params.op) : {}; + filter.faversion = Config.fastadmin.version; + op.faversion = "="; + params.filter = JSON.stringify(filter); + params.op = JSON.stringify(op); + return params; + } }); // 为表格绑定事件 @@ -64,7 +75,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function var data = table.bootstrapTable("getData"); var item = data[index]; var addon = typeof Config.addons[item.name] != 'undefined' ? Config.addons[item.name] : null; - console.log(item, addon); Layer.alert(Template("addoninfotpl", {item: item, addon: addon}), { btn: [__('OK'), __('Donate'), __('Feedback'), __('Document')], title: __('Detail'), @@ -113,7 +123,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function $(document).on("click", ".btn-addonindex", function () { if ($(this).attr("href") == 'javascript:;') { Layer.msg(__('Not installed tips'), {icon: 7}); - } else if ($(this).parent().find("a.btn-enable").size() > 0) { + } else if ($(this).closest(".operate").find("a.btn-enable").size() > 0) { Layer.msg(__('Not enabled tips'), {icon: 7}); return false; } @@ -187,13 +197,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function $(document).on("click", ".btn-install", function () { var that = this; var name = $(this).closest(".operate").data("name"); + var version = $(this).data("version"); var userinfo = Controller.api.userinfo.get(); var uid = userinfo ? userinfo.id : 0; var token = userinfo ? userinfo.token : ''; var install = function (name, force) { Fast.api.ajax({ url: 'addon/install', - data: {name: name, force: force ? 1 : 0, uid: uid, token: token} + data: {name: name, force: force ? 1 : 0, uid: uid, token: token, version: version, faversion: Config.fastadmin.version} }, function (data, ret) { Layer.closeAll(); Config['addons'][data.addon.name] = ret.data.addon; @@ -367,6 +378,39 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function }; operate(name, action, false); }); + + //点击升级 + $(document).on("click", ".btn-upgrade", function () { + if ($(this).closest(".operate").find("a.btn-disable").size() > 0) { + Layer.alert(__('Please disable addon first'), {icon: 7}); + return false; + } + var name = $(this).closest(".operate").data("name"); + var version = $(this).data("version"); + var userinfo = Controller.api.userinfo.get(); + var uid = userinfo ? userinfo.id : 0; + var token = userinfo ? userinfo.token : ''; + var upgrade = function (name) { + Fast.api.ajax({ + url: 'addon/upgrade', + data: {name: name, uid: uid, token: token, version: version, faversion: Config.fastadmin.version} + }, function (data, ret) { + Config['addons'][name].version = version; + Layer.closeAll(); + $('.btn-refresh').trigger('click'); + }, function (data, ret) { + Layer.alert(ret.msg); + return false; + }); + }; + Layer.confirm(__('Upgrade tips'), function () { + upgrade(name); + }); + }); + + $(document).on("click", ".operate .btn-group .dropdown-toggle", function () { + $(this).closest(".btn-group").toggleClass("dropup", $(document).height() - $(this).offset().top <= 200); + }); }, add: function () { Controller.api.bindevent(); diff --git a/public/assets/js/require-backend.min.js b/public/assets/js/require-backend.min.js index 2d689ca..36b0dae 100644 --- a/public/assets/js/require-backend.min.js +++ b/public/assets/js/require-backend.min.js @@ -9758,7 +9758,9 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr $(toolbar).on('click', Table.config.addbtn, function () { var ids = Table.api.selectedids(table); var url = options.extend.add_url; - url = Table.api.replaceurl(url, {ids: ids.length > 0 ? ids.join(",") : 0}, table); + if (url.indexOf("{ids}") !== -1) { + url = Table.api.replaceurl(url, {ids: ids.length > 0 ? ids.join(",") : 0}, table); + } Fast.api.open(url, __('Add'), $(this).data() || {}); }); // 导入按钮事件 diff --git a/public/assets/js/require-table.js b/public/assets/js/require-table.js index e4e74a2..e740da5 100644 --- a/public/assets/js/require-table.js +++ b/public/assets/js/require-table.js @@ -160,7 +160,9 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table $(toolbar).on('click', Table.config.addbtn, function () { var ids = Table.api.selectedids(table); var url = options.extend.add_url; - url = Table.api.replaceurl(url, {ids: ids.length > 0 ? ids.join(",") : 0}, table); + if (url.indexOf("{ids}") !== -1) { + url = Table.api.replaceurl(url, {ids: ids.length > 0 ? ids.join(",") : 0}, table); + } Fast.api.open(url, __('Add'), $(this).data() || {}); }); // 导入按钮事件 -- libgit2 0.24.0