作者 Karson

新增插件管理本地插件功能

新增插件管理HTTPS提示
新增插件管理登录会会员功能
完善插件管理语言包
修复build_heading的错误
@@ -89,7 +89,7 @@ function build_category_select($name, $type, $selected = null, $attr = [], $head @@ -89,7 +89,7 @@ function build_category_select($name, $type, $selected = null, $attr = [], $head
89 function build_toolbar($btns = NULL, $attr = []) 89 function build_toolbar($btns = NULL, $attr = [])
90 { 90 {
91 $auth = \app\admin\library\Auth::instance(); 91 $auth = \app\admin\library\Auth::instance();
92 - $controller = str_replace('.','/',strtolower(think\Request::instance()->controller())); 92 + $controller = str_replace('.', '/', strtolower(think\Request::instance()->controller()));
93 $btns = $btns ? $btns : ['refresh', 'add', 'edit', 'del']; 93 $btns = $btns ? $btns : ['refresh', 'add', 'edit', 'del'];
94 $btns = is_array($btns) ? $btns : explode(',', $btns); 94 $btns = is_array($btns) ? $btns : explode(',', $btns);
95 $index = array_search('delete', $btns); 95 $index = array_search('delete', $btns);
@@ -125,12 +125,16 @@ function build_toolbar($btns = NULL, $attr = []) @@ -125,12 +125,16 @@ function build_toolbar($btns = NULL, $attr = [])
125 * @param string $content 125 * @param string $content
126 * @return string 126 * @return string
127 */ 127 */
128 -function build_heading($title = NULL, $content = NULL) 128 +function build_heading($title = NULL, $content = NULL, $path = NULL)
129 { 129 {
130 if (is_null($title) && is_null($content)) 130 if (is_null($title) && is_null($content))
131 { 131 {
132 - $path = request()->pathinfo();  
133 - $path = $path[0] == '/' ? $path : '/' . $path; 132 + if (is_null($path))
  133 + {
  134 + $action = request()->action();
  135 + $controller = str_replace('.', '/', request()->controller());
  136 + $path = strtolower($controller . ($action && $action != 'index' ? '/' . $action : ''));
  137 + }
134 // 根据当前的URI自动匹配父节点的标题和备注 138 // 根据当前的URI自动匹配父节点的标题和备注
135 $data = Db::name('auth_rule')->where('name', $path)->field('title,remark')->find(); 139 $data = Db::name('auth_rule')->where('name', $path)->field('title,remark')->find();
136 if ($data) 140 if ($data)
@@ -121,10 +121,12 @@ class Addon extends Backend @@ -121,10 +121,12 @@ class Addon extends Backend
121 } 121 }
122 try 122 try
123 { 123 {
124 - Service::install($name, $force); 124 + $uid = $this->request->post("uid");
  125 + $token = $this->request->post("token");
  126 + Service::install($name, $force, ['uid' => $uid, 'token' => $token]);
125 $info = get_addon_info($name); 127 $info = get_addon_info($name);
126 $info['config'] = get_addon_config($name) ? 1 : 0; 128 $info['config'] = get_addon_config($name) ? 1 : 0;
127 - $this->success("安装成功", null, ['addon' => $info]); 129 + $this->success(__('Install successful'), null, ['addon' => $info]);
128 } 130 }
129 catch (AddonException $e) 131 catch (AddonException $e)
130 { 132 {
@@ -150,7 +152,7 @@ class Addon extends Backend @@ -150,7 +152,7 @@ class Addon extends Backend
150 try 152 try
151 { 153 {
152 Service::uninstall($name, $force); 154 Service::uninstall($name, $force);
153 - $this->success("卸载成功"); 155 + $this->success(__('Uninstall successful'));
154 } 156 }
155 catch (AddonException $e) 157 catch (AddonException $e)
156 { 158 {
@@ -179,7 +181,7 @@ class Addon extends Backend @@ -179,7 +181,7 @@ class Addon extends Backend
179 $action = $action == 'enable' ? $action : 'disable'; 181 $action = $action == 'enable' ? $action : 'disable';
180 //调用启用、禁用的方法 182 //调用启用、禁用的方法
181 Service::$action($name, $force); 183 Service::$action($name, $force);
182 - $this->success("操作成功"); 184 + $this->success(__('Operate successful'));
183 } 185 }
184 catch (AddonException $e) 186 catch (AddonException $e)
185 { 187 {
@@ -197,7 +199,7 @@ class Addon extends Backend @@ -197,7 +199,7 @@ class Addon extends Backend
197 public function local() 199 public function local()
198 { 200 {
199 Config::set('default_return_type', 'json'); 201 Config::set('default_return_type', 'json');
200 - 202 +
201 $file = $this->request->file('file'); 203 $file = $this->request->file('file');
202 $addonTmpDir = RUNTIME_PATH . 'addons' . DS; 204 $addonTmpDir = RUNTIME_PATH . 'addons' . DS;
203 if (!is_dir($addonTmpDir)) 205 if (!is_dir($addonTmpDir))
@@ -217,20 +219,20 @@ class Addon extends Backend @@ -217,20 +219,20 @@ class Addon extends Backend
217 $infoFile = $tmpAddonDir . 'info.ini'; 219 $infoFile = $tmpAddonDir . 'info.ini';
218 if (!is_file($infoFile)) 220 if (!is_file($infoFile))
219 { 221 {
220 - throw new Exception("插件配置文件未找到"); 222 + throw new Exception(__('Addon info file was not found'));
221 } 223 }
222 224
223 $config = Config::parse($infoFile, '', $tmpName); 225 $config = Config::parse($infoFile, '', $tmpName);
224 $name = isset($config['name']) ? $config['name'] : ''; 226 $name = isset($config['name']) ? $config['name'] : '';
225 if (!$name) 227 if (!$name)
226 { 228 {
227 - throw new Exception("插件配置信息不正确"); 229 + throw new Exception(__('Addon info file data incorrect'));
228 } 230 }
229 231
230 $newAddonDir = ADDON_PATH . $name . DS; 232 $newAddonDir = ADDON_PATH . $name . DS;
231 if (is_dir($newAddonDir)) 233 if (is_dir($newAddonDir))
232 { 234 {
233 - throw new Exception("上传的插件已经存在"); 235 + throw new Exception(__('Addon already exists'));
234 } 236 }
235 237
236 //重命名插件文件夹 238 //重命名插件文件夹
@@ -255,9 +257,9 @@ class Addon extends Backend @@ -255,9 +257,9 @@ class Addon extends Backend
255 257
256 //导入SQL 258 //导入SQL
257 Service::importsql($name); 259 Service::importsql($name);
258 - 260 +
259 $info['config'] = get_addon_config($name) ? 1 : 0; 261 $info['config'] = get_addon_config($name) ? 1 : 0;
260 - $this->success("插件安装成功,你需要手动启用该插件,使之生效", null, ['addon' => $info]); 262 + $this->success(__('Installed tips'), null, ['addon' => $info]);
261 } 263 }
262 catch (Exception $e) 264 catch (Exception $e)
263 { 265 {
@@ -287,7 +289,7 @@ class Addon extends Backend @@ -287,7 +289,7 @@ class Addon extends Backend
287 try 289 try
288 { 290 {
289 Service::refresh(); 291 Service::refresh();
290 - $this->success("操作成功"); 292 + $this->success(__('Operate successful'));
291 } 293 }
292 catch (Exception $e) 294 catch (Exception $e)
293 { 295 {
@@ -295,4 +297,53 @@ class Addon extends Backend @@ -295,4 +297,53 @@ class Addon extends Backend
295 } 297 }
296 } 298 }
297 299
  300 + /**
  301 + * 已装插件
  302 + */
  303 + public function downloaded()
  304 + {
  305 + $offset = (int) $this->request->get("offset");
  306 + $limit = (int) $this->request->get("limit");
  307 + $filter = $this->request->get("filter");
  308 + $filter = (array) json_decode($filter, true);
  309 + foreach ($filter as $k => &$v)
  310 + {
  311 + $v = htmlspecialchars(strip_tags($v));
  312 + }
  313 + unset($v);
  314 + $where = ['status' => 'normal'];
  315 + if (isset($filter['id']))
  316 + {
  317 + $where['id'] = (int) $filter['id'];
  318 + }
  319 + if (isset($filter['name']))
  320 + {
  321 + $where['name'] = ['like', "%{$filter['name']}%"];
  322 + }
  323 + if (isset($filter['title']))
  324 + {
  325 + $where['title'] = ['like', "%{$filter['title']}%"];
  326 + }
  327 +
  328 + $addons = get_addon_list();
  329 + $list = [];
  330 + foreach ($addons as $k => $v)
  331 + {
  332 + $v['flag'] = '';
  333 + $v['banner'] = '';
  334 + $v['image'] = '';
  335 + $v['donateimage'] = '';
  336 + $v['demourl'] = '';
  337 + $v['price'] = '0.00';
  338 + $v['url'] = '/addons/' . $v['name'];
  339 + $v['createtime'] = 0;
  340 + $list[] = $v;
  341 + }
  342 + $list = array_slice($list, $offset, $limit);
  343 + $result = array("total" => count($addons), "rows" => $list);
  344 +
  345 + $callback = $this->request->get('callback') ? "jsonp" : "json";
  346 + return $callback($result);
  347 + }
  348 +
298 } 349 }
1 <?php 1 <?php
2 2
3 return [ 3 return [
4 - 'Id' => 'ID',  
5 - 'Title' => '标题',  
6 - 'Value' => '配置值',  
7 - 'Array key' => '键',  
8 - 'Array value' => '值', 4 + 'Id' => 'ID',
  5 + 'Title' => '标题',
  6 + 'Value' => '配置值',
  7 + 'Array key' => '键',
  8 + 'Array value' => '值',
  9 + 'File' => '文件',
  10 + 'Warmtips' => '温馨提示',
  11 + 'Offline install' => '离线安装',
  12 + 'Refresh addon cache' => '刷新插件缓存',
  13 + 'Userinfo' => '会员信息',
  14 + 'Online store' => '在线商店',
  15 + 'Local addon' => '本地插件',
  16 + 'Https tips' => '当前你无法在插件管理中在线安装FastAdmin市场中的插件,请前往 <a href="http://www.fastadmin.net/store.html" target="_blank" class="">FastAdmin插件市场</a> 中下载后进行离线安装。',
  17 + 'Conflict tips' => '此插件中发现和现有系统中部分文件发现冲突!以下文件将会被影响,请备份好相关文件后再继续操作',
  18 + 'Login tips' => '此处登录账号为<a href="http://www.fastadmin.net" target="_blank">FastAdmin官网账号</a>',
  19 + 'Logined tips' => '你好!%s<br />当前你已经登录,将同步保存你的购买记录',
  20 + 'Pay tips' => '支付完成后请稍等1~5分钟后再尝试安装,请不要重复支付,如果仍然无法安装,请加<a href="https://jq.qq.com/?_wv=1027&k=487PNBb" target="_blank">QQ群:636393962</a>向管理员反馈',
  21 + 'Pay click tips' => '请点击这里在新窗口中进行支付!',
  22 + 'Pay new window tips' => '请在新弹出的窗口中进行支付,支付完成后再重新点击安装按钮进行安装!',
  23 + 'Uninstall tips' => '确认卸载插件?<p class="text-danger">卸载将会删除所有插件文件且不可找回!!! 插件如果有创建数据库表请手动删除!!!</p>如有重要数据请备份后再操作!',
  24 + 'Installed tips' => '插件安装成功,你需要手动启用该插件,使之生效',
  25 + 'Recommend' => '推荐',
  26 + 'Hot' => '热门',
  27 + 'New' => '新',
  28 + 'Free' => '免费',
  29 + 'Sale' => '折扣',
  30 + 'No image' => '暂无缩略图',
  31 + 'Author' => '作者',
  32 + 'Intro' => '介绍',
  33 + 'Version' => '版本',
  34 + 'Createtime' => '添加时间',
  35 + 'Demo' => '在线演示',
  36 + 'Install' => '安装',
  37 + 'Uninstall' => '卸载',
  38 + 'Setting' => '配置',
  39 + 'Disable' => '禁用',
  40 + 'Enable' => '启用',
  41 + 'Your username or email' => '你的用户名或邮箱',
  42 + 'Your password' => '你的密码',
  43 + 'Login FastAdmin' => '登录FastAdmin',
  44 + 'Login' => '登录',
  45 + 'Logout' => '退出登录',
  46 + 'Register' => '注册账号',
  47 + 'You\'re not login' => '当前未登录',
  48 + 'Pay now' => '立即支付',
  49 + 'Continue install' => '继续安装',
  50 + 'Continue uninstall' => '继续安装',
  51 + 'Continue operate' => '继续操作',
  52 + 'Install successful' => '安装成功',
  53 + 'Uninstall successful' => '卸载成功',
  54 + 'Operate successful' => '操作成功',
  55 + 'Addon info file was not found' => '插件配置文件未找到',
  56 + 'Addon info file data incorrect' => '插件配置文件未找到',
  57 + 'Addon info file data incorrect' => '插件配置信息不正确',
  58 + 'Addon already exists' => '上传的插件已经存在',
9 ]; 59 ];
1 <style type="text/css"> 1 <style type="text/css">
  2 + .item-addon{margin-left:15px;margin-bottom:15px;}
  3 + .item-addon img.img-responsive,.item-addon .noimage{width: 300px;height:200px;}
  4 + .noimage {line-height: 200px;text-align: center;background:#18bc9c;color:#fff;}
2 .addon { 5 .addon {
3 - height:100%;position: relative; 6 + position: relative;
4 } 7 }
5 .addon > span { 8 .addon > span {
6 position:absolute;left:15px;top:15px; 9 position:absolute;left:15px;top:15px;
@@ -10,6 +13,10 @@ @@ -10,6 +13,10 @@
10 } 13 }
11 .layui-layer-pay {border:none;} 14 .layui-layer-pay {border:none;}
12 </style> 15 </style>
  16 +<div id="warmtips" class="alert alert-dismissable alert-danger hide">
  17 + <button type="button" class="close" data-dismiss="alert">×</button>
  18 + <strong>{:__('Warning')}</strong> {:__('Https tips')}
  19 +</div>
13 <div class="panel panel-default panel-intro"> 20 <div class="panel panel-default panel-intro">
14 {:build_heading()} 21 {:build_heading()}
15 22
@@ -19,8 +26,11 @@ @@ -19,8 +26,11 @@
19 <div class="widget-body no-padding"> 26 <div class="widget-body no-padding">
20 <div id="toolbar" class="toolbar"> 27 <div id="toolbar" class="toolbar">
21 {:build_toolbar('refresh')} 28 {:build_toolbar('refresh')}
22 - <button type="button" id="plupload-addon" class="btn btn-danger plupload" data-url="addon/local" data-mimetype="application/zip" data-multiple="false"><i class="fa fa-upload"></i> {:__('本地安装')}</button>  
23 - <a class="btn btn-success btn-ajax" href="addon/refresh"><i class="fa fa-refresh"></i> {:__('刷新插件缓存')}</a> 29 + <button type="button" id="plupload-addon" class="btn btn-danger plupload" data-url="addon/local" data-mimetype="application/zip" data-multiple="false"><i class="fa fa-upload"></i> {:__('Offline install')}</button>
  30 + <a class="btn btn-success btn-ajax" href="addon/refresh"><i class="fa fa-refresh"></i> {:__('Refresh addon cache')}</a>
  31 + <a class="btn btn-info btn-switch btn-store" href="javascript:;" data-url="{$config.fastadmin.api_url}/addon/index"><i class="fa fa-cloud"></i> {:__('Online store')}</a>
  32 + <a class="btn btn-info btn-switch" href="javascript:;" data-url="addon/downloaded"><i class="fa fa-laptop"></i> {:__('Local addon')}</a>
  33 + <a class="btn btn-primary btn-userinfo" href="javascript:;"><i class="fa fa-user"></i> {:__('Userinfo')}</a>
24 </div> 34 </div>
25 <table id="table" class="table table-striped table-hover" width="100%"> 35 <table id="table" class="table table-striped table-hover" width="100%">
26 36
@@ -32,6 +42,42 @@ @@ -32,6 +42,42 @@
32 </div> 42 </div>
33 </div> 43 </div>
34 </div> 44 </div>
  45 +<script id="logintpl" type="text/html">
  46 + <div>
  47 + <form class="form-horizontal">
  48 + <fieldset>
  49 + <div class="alert alert-dismissable alert-danger">
  50 + <button type="button" class="close" data-dismiss="alert">×</button>
  51 + <strong>{:__('Warning')}</strong><br />{:__('Login tips')}
  52 + </div>
  53 + <div class="form-group">
  54 + <label for="inputAccount" class="col-lg-3 control-label">{:__('Username')}</label>
  55 + <div class="col-lg-9">
  56 + <input type="text" class="form-control" id="inputAccount" value="" placeholder="{:__('Your username or email')}">
  57 + </div>
  58 + </div>
  59 + <div class="form-group">
  60 + <label for="inputPassword" class="col-lg-3 control-label">{:__('Password')}</label>
  61 + <div class="col-lg-9">
  62 + <input type="password" class="form-control" id="inputPassword" value="" placeholder="{:__('Your password')}">
  63 + </div>
  64 + </div>
  65 + </fieldset>
  66 + </form>
  67 + </div>
  68 +</script>
  69 +<script id="userinfotpl" type="text/html">
  70 + <div>
  71 + <form class="form-horizontal">
  72 + <fieldset>
  73 + <div class="alert alert-dismissable alert-success">
  74 + <button type="button" class="close" data-dismiss="alert">×</button>
  75 + <strong>{:__('Warning')}</strong><br />{:__('Logined tips', '<%=username%>')}
  76 + </div>
  77 + </fieldset>
  78 + </form>
  79 + </div>
  80 +</script>
35 <script id="paytpl" type="text/html"> 81 <script id="paytpl" type="text/html">
36 <div style="position:relative;width:800px;height:600px;background:url('<%=payimg%>') 0 0 no-repeat;"> 82 <div style="position:relative;width:800px;height:600px;background:url('<%=payimg%>') 0 0 no-repeat;">
37 <div style="position:absolute;left:265px;top:442px;"> 83 <div style="position:absolute;left:265px;top:442px;">
@@ -45,13 +91,13 @@ @@ -45,13 +91,13 @@
45 <script id="conflicttpl" type="text/html"> 91 <script id="conflicttpl" type="text/html">
46 <div class="alert alert-dismissable alert-danger"> 92 <div class="alert alert-dismissable alert-danger">
47 <button type="button" class="close" data-dismiss="alert">×</button> 93 <button type="button" class="close" data-dismiss="alert">×</button>
48 - <strong>警告!</strong> 此插件中发现和现有系统中部分文件发现冲突!以下文件将会被影响,请备份好相关文件后再继续操 94 + <strong>{:__('Warning')}</strong> {:__('Conflict tips')}
49 </div> 95 </div>
50 <table class="table table-striped"> 96 <table class="table table-striped">
51 <thead> 97 <thead>
52 <tr> 98 <tr>
53 <th>#</th> 99 <th>#</th>
54 - <th>文件</th> 100 + <th>{:__('File')}</th>
55 </tr> 101 </tr>
56 </thead> 102 </thead>
57 <tbody> 103 <tbody>
@@ -65,47 +111,56 @@ @@ -65,47 +111,56 @@
65 </table> 111 </table>
66 </script> 112 </script>
67 <script id="itemtpl" type="text/html"> 113 <script id="itemtpl" type="text/html">
68 - <div class="col-sm-4 col-md-3"> 114 + <div class="item-addon">
69 <% var labelarr = ['primary', 'success', 'info', 'danger', 'warning']; %> 115 <% var labelarr = ['primary', 'success', 'info', 'danger', 'warning']; %>
70 <% var label = labelarr[item.id % 5]; %> 116 <% var label = labelarr[item.id % 5]; %>
71 <% var addon = typeof addons[item.name]!= 'undefined' ? addons[item.name] : null; %> 117 <% var addon = typeof addons[item.name]!= 'undefined' ? addons[item.name] : null; %>
72 <div class="thumbnail addon"> 118 <div class="thumbnail addon">
73 <!--<span class="btn btn-<%=label%>">ID:<%=item.id%></span>--> 119 <!--<span class="btn btn-<%=label%>">ID:<%=item.id%></span>-->
74 - <a href="<%=addon?addon.url:'javascript:;'%>" target="_blank"><img src="<%=item.image%>" class="img-responsive" alt="<%=item.title%>"></a> 120 + <a href="<%=addon?addon.url:'javascript:;'%>" target="_blank">
  121 + <%if(item.image){%>
  122 + <img src="<%=item.image%>" class="img-responsive" alt="<%=item.title%>">
  123 + <%}else{%>
  124 + <div class="noimage">{:__('No image')}</div>
  125 + <%}%>
  126 + </a>
75 <div class="caption"> 127 <div class="caption">
76 - <h4><%=item.title?item.title:''%> 128 + <h4><%=item.title?item.title:'{:__('None')}'%>
77 <% if(item.flag.indexOf("recommend")>-1){%> 129 <% if(item.flag.indexOf("recommend")>-1){%>
78 - <span class="label label-success">推荐</span> 130 + <span class="label label-success">{:__('Recommend')}</span>
79 <% } %> 131 <% } %>
80 <% if(item.flag.indexOf("hot")>-1){%> 132 <% if(item.flag.indexOf("hot")>-1){%>
81 - <span class="label label-danger">热门</span> 133 + <span class="label label-danger">{:__('Hot')}</span>
82 <% } %> 134 <% } %>
83 <% if(item.flag.indexOf("free")>-1){%> 135 <% if(item.flag.indexOf("free")>-1){%>
84 - <span class="label label-info">免费</span> 136 + <span class="label label-info">{:__('Free')}</span>
85 <% } %> 137 <% } %>
86 <% if(item.flag.indexOf("sale")>-1){%> 138 <% if(item.flag.indexOf("sale")>-1){%>
87 - <span class="label label-warning">折扣</span> 139 + <span class="label label-warning">{:__('Sale')}</span>
88 <% } %> 140 <% } %>
89 </h4> 141 </h4>
90 <p class="text-<%=item.price>0?'danger':'success'%>"><b><%=item.price%></b></p> 142 <p class="text-<%=item.price>0?'danger':'success'%>"><b><%=item.price%></b></p>
91 - <p class="text-muted">作者: <a href="<%=item.url?item.url:'javascript:;'%>" target="_blank"><%=item.author%></a></p>  
92 - <p class="text-muted">描述: <%=item.intro%></p>  
93 - <p class="text-muted">版本: <%=# 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>  
94 - <p class="text-muted">添加时间: <%=Moment(item.createtime*1000).format("YYYY-MM-DD HH:mm:ss")%></p>  
95 - <!--<p class="text-muted">最后时间: <%=Moment(item.updatetime*1000).format("YYYY-MM-DD HH:mm:ss")%></p>--> 143 + <p class="text-muted">{:__('Author')}: <a href="<%=item.url?item.url:'javascript:;'%>" target="_blank"><%=item.author%></a></p>
  144 + <p class="text-muted">{:__('Intro')}: <%=item.intro%></p>
  145 + <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>
  146 + <p class="text-muted">{:__('Createtime')}: <%=Moment(item.createtime*1000).format("YYYY-MM-DD HH:mm:ss")%></p>
96 <p class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>"> 147 <p class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>">
97 <% if(!addon){ %> 148 <% if(!addon){ %>
98 - <a href="javascript:;" class="btn btn-primary btn-success btn-install"><i class="fa fa-cloud-download"></i> 安装</a> 149 + <a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
  150 + <% if(item.demourl){ %>
  151 + <a href="<%=item.demourl%>" class="btn btn-primary btn-info btn-demo" target="_blank"><i class="fa fa-flash"></i> {:__('Demo')}</a>
  152 + <% } %>
99 <% } %> 153 <% } %>
  154 +
100 <% if(addon){ %> 155 <% if(addon){ %>
101 <% if(addon.config){ %> 156 <% if(addon.config){ %>
102 - <a href="javascript:;" class="btn btn-primary btn-config"><i class="fa fa-pencil"></i> 配置</a> 157 + <a href="javascript:;" class="btn btn-primary btn-config"><i class="fa fa-pencil"></i> {:__('Setting')}</a>
103 <% } %> 158 <% } %>
104 <% if(addon.state == "1"){ %> 159 <% if(addon.state == "1"){ %>
105 - <a href="javascript:;" class="btn btn-warning btn-disable" data-action="disable"><i class="fa fa-times"></i> 点击禁用</a> 160 + <a href="javascript:;" class="btn btn-warning btn-disable" data-action="disable"><i class="fa fa-times"></i> {:__('Disable')}</a>
106 <% }else{ %> 161 <% }else{ %>
107 - <a href="javascript:;" class="btn btn-success btn-enable" data-action="enable"><i class="fa fa-check"></i> 点击启用</a>  
108 - <a href="javascript:;" class="btn btn-danger btn-uninstall"><i class="fa fa-times"></i> 卸载</a> 162 + <a href="javascript:;" class="btn btn-success btn-enable" data-action="enable"><i class="fa fa-check"></i> {:__('Enable')}</a>
  163 + <a href="javascript:;" class="btn btn-danger btn-uninstall"><i class="fa fa-times"></i> {:__('Uninstall')}</a>
109 <% } %> 164 <% } %>
110 <% } %> 165 <% } %>
111 <!-- 166 <!--
@@ -19,7 +19,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -19,7 +19,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
19 19
20 // 初始化表格 20 // 初始化表格
21 table.bootstrapTable({ 21 table.bootstrapTable({
22 - url: $.fn.bootstrapTable.defaults.extend.index_url, 22 + url: location.protocol === "https:" ? "addon/downloaded" : $.fn.bootstrapTable.defaults.extend.index_url,
23 columns: [ 23 columns: [
24 [ 24 [
25 {field: 'id', title: 'ID'}, 25 {field: 'id', title: 'ID'},
@@ -27,6 +27,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -27,6 +27,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
27 {field: 'title', title: __('Title')} 27 {field: 'title', title: __('Title')}
28 ] 28 ]
29 ], 29 ],
  30 + dataType: 'jsonp',
30 templateView: true, 31 templateView: true,
31 search: false, 32 search: false,
32 showColumns: false, 33 showColumns: false,
@@ -34,12 +35,18 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -34,12 +35,18 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
34 showExport: false, 35 showExport: false,
35 commonSearch: true, 36 commonSearch: true,
36 searchFormVisible: false, 37 searchFormVisible: false,
37 - pageSize: 12 38 + pageSize: 10
38 }); 39 });
39 40
40 // 为表格绑定事件 41 // 为表格绑定事件
41 Table.api.bindevent(table); 42 Table.api.bindevent(table);
42 43
  44 + // 如果是https则启用提示
  45 + if (location.protocol === "https:") {
  46 + $("#warmtips").removeClass("hide");
  47 + $(".btn-switch,.btn-userinfo").addClass("disabled");
  48 + }
  49 +
43 require(['upload'], function (Upload) { 50 require(['upload'], function (Upload) {
44 Upload.api.plupload("#plupload-addon", function (data, ret) { 51 Upload.api.plupload("#plupload-addon", function (data, ret) {
45 Config['addons'][data.addon.name] = data.addon; 52 Config['addons'][data.addon.name] = data.addon;
@@ -48,13 +55,79 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -48,13 +55,79 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
48 }); 55 });
49 }); 56 });
50 57
51 - //点击安装 58 + //切换URL
  59 + $(document).on("click", ".btn-switch", function () {
  60 + table.bootstrapTable('refresh', {url: $(this).data("url"), pageNumber: 1});
  61 + });
  62 + // 会员信息
  63 + $(document).on("click", ".btn-userinfo", function () {
  64 + var userinfo = Controller.api.userinfo.get();
  65 + if (!userinfo) {
  66 + Layer.open({
  67 + content: Template("logintpl", {}),
  68 + area: ['400px', '330px'],
  69 + title: __('Login FastAdmin'),
  70 + resize: false,
  71 + btn: [__('Login'), __('Register')],
  72 + yes: function (index, layero) {
  73 + Fast.api.ajax({
  74 + url: Config.fastadmin.api_url + '/user/login',
  75 + dataType: 'jsonp',
  76 + data: {account: $("#inputAccount", layero).val(), password: $("#inputPassword", layero).val(), _method: 'POST'}
  77 + }, function (data, ret) {
  78 + Controller.api.userinfo.set(data);
  79 + Layer.closeAll();
  80 + Layer.alert(ret.msg);
  81 + }, function (data, ret) {
  82 + Layer.alert(ret.msg);
  83 + });
  84 + },
  85 + btn2: function () {
  86 + return false;
  87 + },
  88 + success: function (layero, index) {
  89 + $(".layui-layer-btn1", layero).prop("href", "http://www.fastadmin.net/user/register.html").prop("target", "_blank");
  90 + }
  91 + });
  92 + } else {
  93 + var userinfo = Controller.api.userinfo.get();
  94 + if (!userinfo) {
  95 + Layer.alert(__('You\'re not login'));
  96 + return false;
  97 + }
  98 + Layer.open({
  99 + content: Template("userinfotpl", userinfo),
  100 + area: ['400px', '330px'],
  101 + title: __('Userinfo'),
  102 + resize: false,
  103 + btn: [__('Logout'), __('Cancel')],
  104 + yes: function () {
  105 + Fast.api.ajax({
  106 + url: Config.fastadmin.api_url + '/user/logout',
  107 + dataType: 'jsonp',
  108 + data: {uid: userinfo.id, token: userinfo.token}
  109 + }, function (data, ret) {
  110 + Controller.api.userinfo.set(null);
  111 + Layer.closeAll();
  112 + Layer.alert(ret.msg);
  113 + }, function (data, ret) {
  114 + Layer.alert(ret.msg);
  115 + });
  116 + }
  117 + });
  118 + }
  119 + });
  120 +
  121 + // 点击安装
52 $(document).on("click", ".btn-install", function () { 122 $(document).on("click", ".btn-install", function () {
53 var name = $(this).closest(".operate").data("name"); 123 var name = $(this).closest(".operate").data("name");
  124 + var userinfo = Controller.api.userinfo.get();
  125 + var uid = userinfo ? userinfo.id : 0;
  126 + var token = userinfo ? userinfo.token : '';
54 var install = function (name, force) { 127 var install = function (name, force) {
55 Fast.api.ajax({ 128 Fast.api.ajax({
56 url: 'addon/install', 129 url: 'addon/install',
57 - data: {name: name, force: force ? 1 : 0} 130 + data: {name: name, force: force ? 1 : 0, uid: uid, token: token}
58 }, function (data, ret) { 131 }, function (data, ret) {
59 Layer.closeAll(); 132 Layer.closeAll();
60 Config['addons'][data.addon.name] = ret.data.addon; 133 Config['addons'][data.addon.name] = ret.data.addon;
@@ -73,19 +146,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -73,19 +146,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
73 btn: false, 146 btn: false,
74 resize: false, 147 resize: false,
75 end: function () { 148 end: function () {
76 - Layer.alert("支付完成后请稍等1~5分钟后再尝试安装,请不要重复支付,如果仍然无法安装,请加<a href='https://jq.qq.com/?_wv=1027&k=487PNBb' target='_blank'>QQ群:636393962</a>向管理员反馈"); 149 + Layer.alert(__('Pay tips'));
77 } 150 }
78 }); 151 });
79 } else if (ret && ret.code === -2) { 152 } else if (ret && ret.code === -2) {
80 //跳转支付 153 //跳转支付
81 - Layer.alert('请点击这里在新窗口中进行支付!', {  
82 - btn: ['立即支付', '取消'], 154 + Layer.alert(__('Pay click tips'), {
  155 + btn: [__('Pay now'), __('Cancel')],
83 icon: 0, 156 icon: 0,
84 success: function (layero) { 157 success: function (layero) {
85 $(".layui-layer-btn0", layero).attr("href", ret.data.payurl).attr("target", "_blank"); 158 $(".layui-layer-btn0", layero).attr("href", ret.data.payurl).attr("target", "_blank");
86 } 159 }
87 }, function () { 160 }, function () {
88 - Layer.alert("请在新弹出的窗口中进行支付,支付完成后再重新点击安装按钮进行安装!", {icon: 0}); 161 + Layer.alert(__('Pay new window tips'), {icon: 0});
89 }); 162 });
90 163
91 } else if (ret && ret.code === -3) { 164 } else if (ret && ret.code === -3) {
@@ -94,8 +167,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -94,8 +167,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
94 content: Template("conflicttpl", ret.data), 167 content: Template("conflicttpl", ret.data),
95 shade: 0.8, 168 shade: 0.8,
96 area: ['800px', '600px'], 169 area: ['800px', '600px'],
97 - title: "温馨提示",  
98 - btn: ['继续安装', '取消'], 170 + title: __('Warning'),
  171 + btn: [__('Continue install'), __('Cancel')],
99 end: function () { 172 end: function () {
100 173
101 }, 174 },
@@ -131,8 +204,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -131,8 +204,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
131 content: Template("conflicttpl", ret.data), 204 content: Template("conflicttpl", ret.data),
132 shade: 0.8, 205 shade: 0.8,
133 area: ['800px', '600px'], 206 area: ['800px', '600px'],
134 - title: "温馨提示",  
135 - btn: ['继续卸载', '取消'], 207 + title: __('Warning'),
  208 + btn: [__('Continue uninstall'), __('Cancel')],
136 end: function () { 209 end: function () {
137 210
138 }, 211 },
@@ -147,7 +220,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -147,7 +220,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
147 return false; 220 return false;
148 }); 221 });
149 }; 222 };
150 - Layer.confirm("确认卸载插件?<p class='text-danger'>卸载将会删除所有插件文件且不可找回!!! 插件如果有创建数据库表请手动删除!!!</p>如有重要数据请备份后再操作!", function () { 223 + Layer.confirm(__('Uninstall tips'), function () {
151 uninstall(name, false); 224 uninstall(name, false);
152 }); 225 });
153 }); 226 });
@@ -155,7 +228,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -155,7 +228,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
155 //点击配置 228 //点击配置
156 $(document).on("click", ".btn-config", function () { 229 $(document).on("click", ".btn-config", function () {
157 var name = $(this).closest(".operate").data("name"); 230 var name = $(this).closest(".operate").data("name");
158 - Fast.api.open("addon/config?name=" + name, "修改配置"); 231 + Fast.api.open("addon/config?name=" + name, __('Setting'));
159 }); 232 });
160 233
161 //点击启用/禁用 234 //点击启用/禁用
@@ -178,8 +251,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -178,8 +251,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
178 content: Template("conflicttpl", ret.data), 251 content: Template("conflicttpl", ret.data),
179 shade: 0.8, 252 shade: 0.8,
180 area: ['800px', '600px'], 253 area: ['800px', '600px'],
181 - title: "温馨提示",  
182 - btn: ['继续操作', '取消'], 254 + title: __('Warning'),
  255 + btn: [__('Continue operate'), __('Cancel')],
183 end: function () { 256 end: function () {
184 257
185 }, 258 },
@@ -206,6 +279,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -206,6 +279,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
206 api: { 279 api: {
207 bindevent: function () { 280 bindevent: function () {
208 Form.api.bindevent($("form[role=form]")); 281 Form.api.bindevent($("form[role=form]"));
  282 + },
  283 + userinfo: {
  284 + get: function () {
  285 + var userinfo = localStorage.getItem("fastadmin_userinfo");
  286 + return userinfo ? JSON.parse(userinfo) : null;
  287 + },
  288 + set: function (data) {
  289 + if (data) {
  290 + localStorage.setItem("fastadmin_userinfo", JSON.stringify(data));
  291 + } else {
  292 + localStorage.removeItem("fastadmin_userinfo");
  293 + }
  294 + }
209 } 295 }
210 } 296 }
211 }; 297 };